Reusing JAX RS Client in multi-threaded environment (with resteasy) - java

According to the documentation,
"Clients are heavy-weight objects that manage the client-side
communication infrastructure. Initialization as well as disposal of a
Client instance may be a rather expensive operation. It is therefore
advised to construct only a small number of Client instances in the
application. "
Ok, I'm trying to cache Client itself and WebTarget instances in a static variable, the someMethod() is invoked in multi-threaded environment:
private static Client client = ClientBuilder.newClient();
private static WebTarget webTarget = client.target("someBaseUrl");
...
public static String someMethod(String arg1, String arg2)
{
WebTarget target = entrTarget.queryParam("arg1", arg1).queryParam("arg2", arg2);
Response response = target.request().get();
final String result = response.readEntity(String.class);
response.close();
return result;
}
But sometimes (not always) I'm get an exception:
Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
How can Client/WebTarget be reused/cached correctly? Is it possible with JAX RS Client API? Or I have to use some framework-specific features (resteasy/jersey) Could you provide some example or documentation?

Your implementation is not thread-safe. When two threads access someMethod at the same time they are sharing the same Client and one will try to make a second request while the first one is not finished.
You have two choices:
Synchronize the access to the Client and WebTarget manually.
Let the container manage concurrency by annotating the enclosing type with #javax.ejb.Singleton which guarantees thread safety. (see chapter 4.8.5 of the EJB specification)
If someMethod in a container managed environment I would use the second approach.

Since this issue is still open at the time of writing (version 3.0.X) RESTEASY: deprecated Apache classes cleanup
You can go deeper to use the newer, non-deprecated classes instead to create you resteasy client. You will also have more control over how you want the pool to be etc.
Here is what I did:
// This will create a threadsafe JAX-RS client using pooled connections.
// Per default this implementation will create no more than than 2
// concurrent connections per given route and no more 20 connections in
// total. (see javadoc of PoolingHttpClientConnectionManager)
PoolingHttpClientConnectionManager cm =
new PoolingHttpClientConnectionManager();
CloseableHttpClient closeableHttpClient =
HttpClientBuilder.create().setConnectionManager(cm).build();
ApacheHttpClient4Engine engine =
new ApacheHttpClient4Engine(closeableHttpClient);
return new ResteasyClientBuilder().httpEngine(engine).build();
Also make sure you release the connection after making a call. Calling response.close() will do that for you so probably put that in a finally block.

First, do not reuse WebTarget. For simplicity, you can always create new WebTarget.
Second, if you're using Resteasy, you can add provided dependency for Resteasy client to your project. Example in Gradle:
provided 'org.jboss.resteasy:resteasy-client:3.0.14.Final'
Then, you can create your connection like this:
ResteasyClientBuilder builder = new ResteasyClientBuilder();
builder.connectionPoolSize(200);
There is no need to set maxPooledPerRoute, this is set automatically by RestEasy (can be found in RestEasyClientBuilder class source code).
When you set connectionPoolSize, you will no longer get error when Client is reused and you can happily re-use them all across the application. I've tried this solution on many projects and it actually works well. But when you deploy your application to a non-resteasy container (like Glassfish), your code won't work and you will have to use ClientBuilder class again.

The documentation is unfortunately not very clear about what can and can't be reused safely. When in doubt reuse nothing. However, if you're determined to minimize overhead you can safely reuse most objects depending on the methods called.
Starting with your code, here's some comments about what's happening:
// (1) Store an instance of Client with its own configuration
private static Client client = ClientBuilder.newClient();
// (2) Store an instance of WebTarget with its own configuration (inherited from client)
private static WebTarget webTarget = client.target("someBaseUrl");
...
public static String someMethod(String arg1, String arg2)
{
// (3) New instance of WebTarget (copy entrTarget config) with "arg1" param
// (4) New instance of WebTarget (copy anonymous config) with "arg2" param
WebTarget target = entrTarget.queryParam("arg1", arg1).queryParam("arg2", arg2);
// (5) New instance of Invocation.Builder (copy target config)
// (6) Invoke GET request with stored configuration
Response response = target.request().get();
final String result = response.readEntity(String.class);
response.close();
return result;
}
I commented on the code as-is but I'm guessing (3) should've referenced the static webTarget field.
A lot of objects are getting created here. Every time an object is created there's a new instance with its own copy of the configuration (so it won't affect its predecessors). In this particular case there should be no race conditions, but there are definitely ways in which this could go wrong.
If on or before (3) you had done something like this (assuming these are legitimate properties):
WebTarget target = webTarget.property("foo", fooProperty).queryParam("arg1", arg1);
Then you would be altering the configuration of the static webTarget field and that could cause a race condition. There are many ways to alter the configuration from the static fields so you either need to guard them carefully or just not have them at all.
Also, be aware that pretty much every object that spawns from the original client will have a reference to it for the purpose of determining if the httpEngine has been closed. So unless you're trying to gracefully shutdown your application it's likely never a good idea to close the client.
And I found out all of this by digging through the source code because there's really no good reference.

Related

Release of resources in AWS Lambda

I implement AWS Lambda function with Java and face with the question - how to release used resources correctly? In my function I make different calls of some resources: execute queries to DB, make REST-calls to third-party services (send StatsD metrics, invoke Slack webhooks, etc), interact with Kinesys stream.
Not going into details, my function looks like this:
public class RequestHandler {
private StatisticsService statsService; //Collect StatsD metrics
private SlackNotificationService slackService; //Send Slack notifications
private SearchService searchService; //Interact with DB
//Simplified version of constructor
public RequestHandler() {
this.statsService = new StatisticsService();
this.slackService = new SlackNotificationService();
this.searchService = new SearchService();
}
public LambdaResponse handleRequest(LambdaRequest request, Context context) {
/**
* Main method of function
* where business-logic is executed
* and all mentioned services are invoked
*/
}
}
And my main question is - where is more correctly release resources which are used in my services, in the end of handleRequest() method (in such case I'll need to open them all again in each next invocation of Lambda-function) or in finalize() method of RequestHandler class?
According to Lambda best practices you should :
Keep alive and reuse connections (HTTP, database, etc.) that were
established during a previous invocation.
So your current code is right.
Regarding the finalize() function, I don't think it is relevant. Lambda execution context will be deleted at some point freeing automatically every open resources.
https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html#function-code

Get underlying soap message of wsimport generated ws client

I'm in the following situation:
I use a wsdl file to generate a webservice client with wsimport.
The generated (central) class looks like this:
#WebServiceClient(...)
public class FooService extends javax.xml.ws.Service
Then I use this class to get a "port"...
Foo port = (new FooService()).getHTTPSPort();
and then I invoke the webservice...
... result = port.foo(...);
where result then will be the server's response as a java bean (with corresponding getters).
I want to obtain the underlying soap message of that result.
So far, I managed to obtain a soap message with the following approach:
I attach a handler to the port binding handler chain...
List<Handler> handlerChainCopy = ((BindingProvider) port).getBinding().getHandlerChain();
handlerChainCopy.add(...);
((BindingProvider) port).getBinding().setHandlerChain(handlerChainCopy);
where my handler looks like this
class MyHandler implements SOAPHandler<SOAPMessageContext> {
private final ByteArrayOutputStream myStream = new ByteArrayOutputStream();
public String getLastMessage(Charset charset){
return new String(this.myStream.toByteArray(), charset);
}
#Override
public boolean handleMessage(SOAPMessageContext context){
this.myStream.reset();
try {
context.getMessage().writeTo(this.myStream);
} catch (Exception ignored) { }
return true /*(don't) block processing*/;
}
...
(I guess, alternatively I could use setHandlerResolver on my fooService object - but that doesn't change my problem, see below.)
And this all works, kind of.
I am not convinced at all that proceeding like this is correct, and I haven't found any documentation that would guarantee correctness.
My main concern is synchronization between result = port.foo(...) and myHandler.getLastMessage(...).
(Of course, I have "control" over new FooService(), but the
Foo port = (new FooService()).getHTTPSPort()
object is dynamically constructed (or obtained!) from the depth of the j2ee server and I have no control whether it is shared between different FooService instances.
Is there any way to guarantee correctness?
Or maybe there is a completly different approach? (Of course, I very much would like to use what wsimport / jax-ws is providing, I don't want to manually implement the complete soap message processing and parsing chain. And I don't want to manually adjust the Result class so that it can store the message, either.)
Thanks
Thomas

GWT manually serialize domain object on server

The first thing my GWT app does when it loads is request the current logged in user from the server via RequestFactory. This blocks because I need properties of the User to know how to proceed. This only takes < 500ms, but it really annoys me that the app is blocked during this time. I already have the User on the server when the jsp is generated, so why not just add the serialized User to the jsp and eliminate this request altogether?
I have two problems keeping me from doing this:
I need to transform User to UserProxy
I need to serialize UserProxy in a way that is easy for GWT to deserialize.
I have not figured out a good way to do #1. This logic appears to be buried in ServiceLayerDecorator without an easy way to isolate? I may be wrong here.
The second one seems easier via ProxySerializer But how do I get my hands on the requestfactory when I am on the server? You cannot call GWT.create on the server.
I have been looking into AutoBeans but this does not handle #1 above. My UserProxy has references to collections of other EntityProxy's that I would like to maintain.
It is possible using AutoBeans if you create an AutoBeanFactory for your proxies:
To transform User to UserProxy:
Create a server side RequestFactory and invoke the same normal request. Response will contain UserProxy (but on the server).
To serialize UserProxy:
AutoBean<UserProxy> bean = AutoBeanUtils.getAutoBean(receivedUserProxy);
String json = AutoBeanCodex.encode(bean).getPayload();
To deserialize UserProxy on client:
AutoBean<UserProxy> bean = AutoBeanCodex.decode(userAutoBeanFactory, UserProxy.class, json);
Creating an in-process RequestFactory on the server (tutorial):
public static <T extends RequestFactory> T create( Class<T> requestFactoryClass ) {
ServiceLayer serviceLayer = ServiceLayer.create();
SimpleRequestProcessor processor = new SimpleRequestProcessor( serviceLayer );
T factory = RequestFactorySource.create( requestFactoryClass );
factory.initialize( new SimpleEventBus(), new InProcessRequestTransport(processor) );
return factory;
}
You could use AutoBeans for this as well if you are able to make User implements UserProxy. It works since Proxies are interfaces with getters/setters:
interface UserFactory implements AutoBeanFactory
{
AutoBean<UserProxy> user(UserProxy toWrap); // wrap existing instance in an AutoBean
}
Then on server you can create the autobean and serialize to json:
UserFactory factory = AutoBeanFactorySource.create(UserFactory.class)
AutoBean<UserProxy> userProxyBean = factory.user( existingUserPojo );
// to convert AutoBean to JSON
String json = AutoBeanCodex.encode(userProxyBean).getPayload();
On the client you can just use AutoBeanCodex.decode to deserialize JSON back to a bean
You cannot call GWT.create on the server (or from any real JVM), but in many cases you can call a JVM-compatible method designed for server use instead. In this case, take a look at RequestFactorySource.create.
It can be a little messy to get the server to read from itself and print out data using RequestFactory - here is a demo example of how this can work (using gwt 2.4, the main branch has the same thing for 2.3 or so) https://github.com/niloc132/tvguide-sample-parent/blob/gwt-2.4.0/tvguide-client/src/main/java/com/acme/gwt/server/TvViewerJsonBootstrap.java - not quite the same thing that you are after, but it may be possible to use this same idea to populate a string in a proxy store that can be read in the client (seen here https://github.com/niloc132/tvguide-sample-parent/blob/gwt-2.4.0/tvguide-client/src/main/java/com/acme/gwt/client/TvGuide.java).
The basic idea is to create a request (including ids, invocations, and with() arguments so the proxy builder makes all the right pieces in a consistent way), and pass it into a SimpleRequestProcessor instance, which will then run it through the server pieces it normally would. (Any entity management system probably should still have the entities cached to avoid an additional lookup, otherwise you need to model some of the work SRP doesn internally.) The ProxySerializer, which wraps a ProxyStore, expects to have full RF messages as sent from the server, so a fair bit of message bookkeeping needs to be done correctly.
I found the answer on the GWT Google Group. All credits go to Nisha Sowdri NM.
Server side encoding:
DefaultProxyStore store = new DefaultProxyStore();
ProxySerializer ser = requests.getSerializer(store);
final String key = ser.serialize(userProxy);
String message = key + ":" + store.encode();
Client side decoding:
String[] parts = message.split(":", 2);
ProxyStore store = new DefaultProxyStore(parts[1]);
ProxySerializer ser = requests.getSerializer(store);
UserProxy user = ser.deserialize(UserProxy.class, parts[0]);

What's the "proper" and right way to keep Jersey Client API functions and REST (Jersey API) Server functions linked?

I was wondering how people with more experience and more complex projects get along with this "uglyness" in the REST Communication. Imagine the following Problem:
We'll need a fair amount of functionalities for one specific resource within our REST Infrastructure, in my case that's about 50+ functions that result in different querys and different responses. I tried to think of a meaningful resource-tree and assigned these to methods that will do "stuff". Afterwards, the Server Resource Class looks like this:
#Path("/thisResource")
public class SomeResource {
#GET/POST/PUT/DELETE
#Path("meaningfulPath")
public Response resourceFunction1 ( ...lots of Params) {
... logic ....
}
//
// lots of functions ...
//
#GET/POST/PUT/DELETE
#Path("meaningfulPath")
public Response resourceFunctionN ( ...lots of Params) {
... logic ....
}
}
To construct the urls my client will call, I made a little function to prevent Typos and to take better use of Constants
so my Client looks like this:
public class Client() {
public returnType function1 () {
client.resource = ResourceClass.build(Constants.Resouce, "meaningfulPath");
...
return response.getEntity(returnType);
}
}
Now the questions that bothers me is how could I link the client function and the server function better?
The only connection between these two blocks of code is the URL that will be called by the client and mapped by the server, and if even this URL is generated somewhere else, this leads to a lot of confusion.
When one of my colleagues needs to get into this code, he has a hard time figuring out which of the 50+ client functions leads to wich server function. Also it is hard to determine if there are obsolete functions in the code, etc. I guess most of you know about the problems of unclean code better than I do.
How do you deal with this? How would you keep this code clean, maintainable and georgeous?
Normally, this would be addressed by EJB or similar technologies.
Or at least by "real" web services, which would provide at least WSDL and schemas (with kind of mapping to Java interfaces, or "ports").
But REST communication is very loosely typed and loosely structured.
The only thing I can think of now, is: define a project (let's call it "Definitions") which would be referenced (hence known) by client and server. In this project you could define a class with a lot of public static final String, such as:
public static final String SOME_METHOD_NAME = "/someMethodName";
public static final String SOME_OTHER_METHOD_NAME = "/someOtherMethodName";
Note: a static final String can very well be referenced by an annotation (in that case it is considered to be constant by the compiler). So use the "constants" to annotate your #Path, such as:
#Path(Definitions.SOME_METHOD_NAME)
Same for the client:
ResourceClass.build(Constants.Resouce, Definitions.SOME_METHOD_NAME);
You are missing the idea behind REST. What you are doing is not REST but RPC over HTTP. Generally you are not supposed to construct URLs using out of band knowledge. Instead you should be following links received in the responses received from the server. Read about HATEOAS:
http://en.wikipedia.org/wiki/HATEOAS

Adding fields to a WebService

I have a SOAP service that exposes a method
TradeDetail getTradeDetail()
TradeDetail stores 5 fields, transaction number, dates etc
I need to add a couple of fields to TradeDetail. I want to keep backward compatibility (for a while) and it looks as if my options are limited to creating a new class with the extra fields
TradeDetail2 getTradeDetail2()
Now this will work - I've done it before. But are there any other solutions that people have used?
E.g.
Fundamentally change TradeDetail2 to add name value pairs.
Inherit TradeDetail2 from TradeDetail, this would reduce code but increase coupling
Return XML or JSON instead
I will be able to retire the original interface pretty quickly so the code will get cleaned up and the extra TradeDetail2 won't last forever!
thanks
I sympathise - some of my webservices are riddled with myMethod(), myMethod2(), myMethod3() etc simply because I needed to add a few new fields.
Would it make sense for you to keep the method name and create a new endpoint for each version of your API instead? eg:
http://my.domain.com/servicename/v1
http://my.domain.com/servicename/v1.1
http://my.domain.com/servicename/v1.5
http://my.domain.com/servicename/v2
Then your method names stay sensible, regardless of how many future changes you need to make.
Any apps using your webservice would probably need to be rewritten and/or rebuilt against a new WSDL anyway in order to take advantage of the new fields, so why not just have them rewritten/rebuilt against the new v1.1 API.
I find that this also helps when communicating with the owners/developers of the apps using your service - eg, "Version [old] of our webservice API will no longer be supported after [date], please ensure that you are using at least version [new]."
This is why I prefer to have complete control over XML to Object mapping, so that I can separate model from XML interface. In your case, I would simply add new fields to TradeDetail, and consider them "optional" for backwards compatibility. This would be the example XML->Object mapping for TradeDetail in framework my team uses, written for your interface:
// this would go into my client endpoint class
public TradeDetail getTradeDetail() {
Element requestRoot = new Element("GetTradeDetail");
Element responseRoot = invokeWebServiceAndReturnJdomElement(requestRoot);
return mapTradeDetail(responseRoot);
}
// this would go into my client XO mapping class
public TradeDetail mapTradeDetail(Element root) {
TradeDetail tradeDetail = new TradeDetail();
tradeDetail.setField1 = fetchString(root, "/GetTradeDetail/Field1");
tradeDetail.setField2 = fetchInteger(root, "/GetTradeDetail/Field2");
tradeDetail.setField3 = mapField3(root, "/GetTradeDetail/Field3");
tradeDetail.setField4 = fetchString(root, "/GetTradeDetail/Field4");
}
This kind of client would ignore new fields, thus being compatible with new version of protocol, until I add something like this to the end of this same method in version 2:
if (fetchXPath(root, "/GetTradeDetail/Field5") != null) {
// so we're talking with server which speaks new version of protocol
tradeDetail.setField5 = fetchString(root, "/GetTradeDetail/Field5");
}
Server would work with similar code, possibly checking client version, and mapping extra fields only if client supports new version of protocol.
In my view, client should be written so that few extra fields added to protocol don't break the client - I don't have the luxury of being down simply because upstream provider added new functionality and didn't inform me about it. If provider changes existing mandatory fields, of course, client needs modification. This is why upstream provider should version protocol and support old version for at least a couple of months.

Categories