juneau-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sblackmon <sblack...@apache.org>
Subject Re: Advice regarding Juneau RestClient, RestCall, Serializers, best practices
Date Wed, 22 Mar 2017 15:20:54 GMT
Thanks James.  Comments below.
On March 20, 2017 at 11:48:16 AM, James Bognar (james.bognar@salesforce.com) wrote:

Hi Steve! 

I'm in training today, so my responses may not be prompt. 

Heads up....in 6.2.0 (what I'm working on now, currently labeled 6.1.1), 
I'm revamping the RestClient code to use builders just like I did for the 
serializers and parsers in 6.1.0. So now's a good time for suggested 
changes! I think the new design makes it considerably easier to understand 
and reuse HttpClients or HttpClientBuilders. 

You're correct that a RestClient only uses a single serializer/parser 
pair. The thoughts were... 
1) You avoid having to specify the Accept and Content-Type on the RestCall 
object. 
2) Typical real-world scenario would be that you're only interested in 
working in a particular language. 

If you anticipate needing support for multiple languages, it won't be 
difficult to add. Most likely with a 'default' language, and if you want 
to use one of the others, you need to do... 
RestClient.doX().setAccept("text/foo").setContentType("text/foo").getResponse(X); 

Let me know if you want this. 
This makes a lot of sense to me.  If it’s possible to also allow for an in-line override
of Serializer or Parser, that would limit the number of RestClients our provider classes need
to create (to 1).



*I also am thinking that a new method on RestClient that allowed you to 
doGet from an request POJO, and have it converted into parameters (using 
BeanMap?) would help make this easier.* 
I'm not sure I understand. Can you provide a code example? (or is it in 
the branch already?) 
Here’s a specific use case from STREAMS-496.

We have an interface that describes the behavior of an external REST endpoint:

https://github.com/steveblackmon/incubator-streams/blob/STREAMS-496/streams-contrib/streams-provider-twitter/src/main/java/org/apache/streams/twitter/api/Statuses.java 

The module contains POJOs for the inputs and outputs of these endpoints, generate from jsonschemas.

https://github.com/steveblackmon/incubator-streams/blob/STREAMS-496/streams-contrib/streams-provider-twitter/src/main/jsonschema/org/apache/streams/twitter/api/StatusesLookupRequest.json

As I understand, If the third-party endpoints worked on the ‘post with json to get json’
model, then we could use juneau’s RemotableProxy capability to execute these transactions
with just the POJOs and the interface, no implementation of the interface required!  Very
cool...
However, the third-party endpoints actually use a ‘get with a bunch of params to get json’
model, and defining the interface methods as a chain of 10+ primitives, most of which are
optional, is ugly and difficult to use in java.  I’d much prefer to define the interface
using a ‘one POJO in, one POJO out’ (like in the links above), and use the fluent builders
on those beans to craft the request objects.

My suggestion is to add a generic swap capability usable by RestClient or RemoteableProxy
that can translate a single (probably flat) POJO argument into get parameters transparently,
so that remotableproxy using get requests with complex argument structures can be as easy
to code and easy to read as those using post requests with payloads.

If this sounds good to you, put it in JIRA and I’ll take a shot at the implementation.



*Also wondering whether type erasure will limit the flexibility of 
restCall.getResponse(T), when the result comes back as a List. In my own 
APIs I always return an Object but a top-level array is fairly common 
practice.* 

The getResponse(Type,Type...) method should allow you to reconstruct 
parameterized lists and maps. 
For example: 
getResponse(LinkedList.class,MyBean.class) - A list of beans. 
getResponse(HashMap.class,String.class,LinkedList.class,MyBean.class) - A 
hashmap with string keys and list of beans values. 

And you can also specify arrays...getResponse(MyBean[].class). 
This is perfect.  I remember now seeing the Type,Type… method in the release notes and
will try it out right away.  Of course, I’m hoping that RemoteableProxy can be used across
the board, if so we won’t need implementation classes that would have to do this at all.



Refer to the Parser#parse(Object input, Type type, Type...args) javadocs 
for info. The RestCall#getResponse() should act the same. 



On Mon, Mar 20, 2017 at 2:55 AM, sblackmon <sblackmon@apache.org> wrote: 

> Hello, 
> 
> I’m working on a class that uses RestClient to implement several 
> contextually related methods. 
> 
> Each method has a POJO describing the request, and a POJO describing the 
> response (some methods return a list of the response POJOs). 
> 
> As I understand from reading docs for 6.1.1-incubating-SNAPSHOT, while a 
> RestServlet may bind multiple Serializers and Parsers, a RestClient may 
> only bind one of each. 
> 
> So i guess that means I need to instantiate a different RestClient for 
> each supported method, or bind a single custom Serializer and Parser that 
> can handle all of the request and response objects? 
> 
> I notice that it’s easy to create and re-use one HttpClient across 
> RestClients, and there’s presumably no problem reusing all the member 
> objects of RestClient, so there should be minimal performance overhead to 
> holding more than one on the class, or even creating a new RestClient for 
> every call is I don’t close the connection. 
> 
> I also am thinking that a new method on RestClient that allowed you to 
> doGet from an request POJO, and have it converted into parameters (using 
> BeanMap?) would help make this easier. 
> 
> Also wondering whether type erasure will limit the flexibility of 
> restCall.getResponse(T), when the result comes back as a List. In my own 
> APIs I always return an Object but a top-level array is fairly common 
> practice. 
> 
> Anyway, I’ve pushed some early work to this branch, and I’d be interested 
> in feedback as I work through this, whether it’s on the right track to 
> minimize code complexity and maximize performance for what we’re trying to 
> do. 
> 
> I’m not yet to the point of running any integration tests using this new 
> implementation but hope to be soon. 
> 
> https://github.com/apache/incubator-streams/compare/ 
> master...steveblackmon:STREAMS-496 
> 
> Thanks in advance, 
> Steve (Streams) 




-- 
James Bognar 

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message