users@jersey.java.net

[Jersey] Re: Jersey client inefficiency?

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Fri, 29 Aug 2014 14:27:51 +0200

On 29 Aug 2014, at 14:05, Mikael Ståldal <mikael.staldal_at_appearnetworks.com> wrote:

> I create and configure a javax.ws.rs.client.Client instace once, and then I reuse it for multiple requests, and in multiple threads.
>
>
> I am doing something like this once:
>
> Client client = ClientBuilder.newBuilder().
> register(MyFirstProvider.class).
> register(MySecondProvider.class).
> register(MyThirdProvider.class).
> register(MultiPartFeature.class).
> property(ClientProperties.CONNECT_TIMEOUT, x).
> property(ClientProperties.READ_TIMEOUT, y);
>
>
> Then for each request I do something like this:
>
> client.target(url).path("foo").
> register(HttpAuthenticationFeature.basic(username, password), 0).
> queryParam("something").request(MediaType.APPLICATION_JSON).get()
>
>
> Is it the HttpAuthenticationFeature that causes this?

Yes. This way you are modifying client runtime providers with every request, forcing it to spawn a new runtime each time. You do not want to do that for every request, you probably want to do this instead:

// Configure the desired web target root to use HTTP Auth feature
WebTarget foo = client.target(url)
                      .path("foo")
                      .register(HttpAuthenticationFeature.basic(username, password), 0);

// Use the pre-configured root web target instance when making requests
foo.queryParam(...something...).request(MediaType.APPLICATION_JSON).get();
foo.queryParam(...something else...).request(MediaType.APPLICATION_JSON).get();
...

> I need to supply different passwords for different requests (and some requests should be without auth), is there another way to do that?

Yes, register the feature only once per client or web target instance and then use properties on the request, see HttpAuthenticationFeature API docs or HTTP Authentication Support section in the Jersey User Guide:

You can change the credentials for each request using properties HTTP_AUTHENTICATION_USERNAME and HTTP_AUTHENTICATION_PASSWORD. Example:

final Response response = client.target("http://localhost:8080/rest/homer/contact").request()
    .property(HTTP_AUTHENTICATION_BASIC_USERNAME, "homer")
    .property(HTTP_AUTHENTICATION_BASIC_PASSWORD, "p1swd745").get();

For requests that do not require authentication, create a separate client or web target instance.

HTH,
Marek

>
> On Fri, Aug 29, 2014 at 12:16 PM, Marek Potociar <marek.potociar_at_oracle.com> wrote:
> Hi Mikael,
>
> Are you configuring different providers on the client for every request? Or are you perhaps creating a new client for each new request?
>
> If yes, then doing a lot of stuff to setup provider injection properly is necessary. If not, then you just found a bug, in which case I would like to ask you to file a new bug against Jersey. I have tried to pick a random E2E client test in Jersey workspace and modified it to send multiple requests (using same and different WebTarget instances) and I was not able to reproduce the behavior you are describing. In my modified test, the org.glassfish.jersey.client.ClientConfig$State.initRuntime() method gets only invoked once, with the first request.
>
> So it seems the problem (if exists) is related to a specific use case. As such I would like to ask you to also attach a simple reproducer unit test that describes the use case and reproduces the issue.
>
> Thank you,
> Marek
>
> On 29 Aug 2014, at 11:51, Mikael Ståldal <mikael.staldal_at_appearnetworks.com> wrote:
>
>> I am using Jersey client 2.12 within a web service implemented with Jersey server 2.12.
>>
>> It seems to me that Jersey client does a lot of stuff every time you make a request, below is a stack trace I was able to capture (Java 7, Jetty 9.2.2).
>>
>> Is it really necessary to do class loading each time you make a request? Cannot this be cached somehow?
>>
>>
>> "qtp330351192-115" prio=10 tid=0x00007f36f8003800 nid=0x321b runnable [0x00007f36b9cd8000]
>> java.lang.Thread.State: RUNNABLE
>> at java.util.zip.ZipFile.freeEntry(Native Method)
>> at java.util.zip.ZipFile.access$1000(ZipFile.java:56)
>> at java.util.zip.ZipFile$1.nextElement(ZipFile.java:514)
>> - locked <0x00000000c007d808> (a java.util.jar.JarFile)
>> at java.util.zip.ZipFile$1.nextElement(ZipFile.java:483)
>> at java.util.jar.JarFile$1.nextElement(JarFile.java:244)
>> at java.util.jar.JarFile$1.nextElement(JarFile.java:239)
>> at sun.misc.URLClassPath$JarLoader.validIndex(URLClassPath.java:803)
>> at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:937)
>> at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:848)
>> at sun.misc.URLClassPath$JarLoader.findResource(URLClassPath.java:818)
>> at sun.misc.URLClassPath$1.next(URLClassPath.java:226)
>> at sun.misc.URLClassPath$1.hasMoreElements(URLClassPath.java:236)
>> at java.net.URLClassLoader$3$1.run(URLClassLoader.java:583)
>> at java.net.URLClassLoader$3$1.run(URLClassLoader.java:581)
>> at java.security.AccessController.doPrivileged(Native Method)
>> at java.net.URLClassLoader$3.next(URLClassLoader.java:580)
>> at java.net.URLClassLoader$3.hasMoreElements(URLClassLoader.java:605)
>> at java.util.Collections.list(Collections.java:3687)
>> at org.eclipse.jetty.webapp.WebAppClassLoader.toList(WebAppClassLoader.java:336)
>> at org.eclipse.jetty.webapp.WebAppClassLoader.getResources(WebAppClassLoader.java:320)
>> at org.glassfish.jersey.internal.ServiceFinder.getResources(ServiceFinder.java:180)
>> at org.glassfish.jersey.internal.ServiceFinder.access$200(ServiceFinder.java:155)
>> at org.glassfish.jersey.internal.ServiceFinder$AbstractLazyIterator.setConfigs(ServiceFinder.java:552)
>> at org.glassfish.jersey.internal.ServiceFinder$AbstractLazyIterator.hasNext(ServiceFinder.java:563)
>> at org.glassfish.jersey.internal.ServiceFinder.toClassArray(ServiceFinder.java:416)
>> at org.glassfish.jersey.internal.ServiceFinderBinder.configure(ServiceFinderBinder.java:90)
>> at org.glassfish.hk2.utilities.binding.AbstractBinder.bind(AbstractBinder.java:171)
>> at org.glassfish.hk2.utilities.binding.AbstractBinder.install(AbstractBinder.java:329)
>> at org.glassfish.jersey.message.internal.MessagingBinders$MessageBodyProviders.configure(MessagingBinders.java:137)
>> at org.glassfish.hk2.utilities.binding.AbstractBinder.bind(AbstractBinder.java:171)
>> at org.glassfish.hk2.utilities.binding.AbstractBinder.install(AbstractBinder.java:329)
>> at org.glassfish.jersey.client.ClientBinder.configure(ClientBinder.java:116)
>> at org.glassfish.hk2.utilities.binding.AbstractBinder.bind(AbstractBinder.java:171)
>> at org.glassfish.jersey.internal.inject.Injections.bind(Injections.java:154)
>> at org.glassfish.jersey.internal.inject.Injections._createLocator(Injections.java:144)
>> at org.glassfish.jersey.internal.inject.Injections.createLocator(Injections.java:133)
>> at org.glassfish.jersey.client.ClientConfig$State.initRuntime(ClientConfig.java:384)
>> at org.glassfish.jersey.client.ClientConfig$State.access$000(ClientConfig.java:86)
>> at org.glassfish.jersey.client.ClientConfig$State$3.get(ClientConfig.java:118)
>> at org.glassfish.jersey.client.ClientConfig$State$3.get(ClientConfig.java:115)
>> at org.glassfish.jersey.internal.util.collection.Values$LazyValueImpl.get(Values.java:322)
>> - locked <0x00000000f6ac1370> (a java.lang.Object)
>> at org.glassfish.jersey.client.ClientConfig.getRuntime(ClientConfig.java:721)
>> at org.glassfish.jersey.client.ClientRequest.getConfiguration(ClientRequest.java:284)
>> at org.glassfish.jersey.client.JerseyInvocation.validateHttpMethodAndEntity(JerseyInvocation.java:125)
>> at org.glassfish.jersey.client.JerseyInvocation.<init>(JerseyInvocation.java:98)
>> at org.glassfish.jersey.client.JerseyInvocation.<init>(JerseyInvocation.java:91)
>> at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:399)
>> at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:303)
>>
>>
>> --
>> Mikael Ståldal
>> Chief Software Architect
>> Appear
>> Phone: +46 8 545 91 572
>> Email: mikael.staldal_at_appearnetworks.com
>
>
>
>
> --
> Mikael Ståldal
> Chief Software Architect
> Appear
> Phone: +46 8 545 91 572
> Email: mikael.staldal_at_appearnetworks.com