I'm building a Jersey web application deployed on Tomcat. I'm having a hard time understanding how to unit test the app.
Testing the core business logic (the non-Jersey-resource classes) is possible by simply instantiating the classes in my tests and calling methods on them (this has nothing to do with Jersey or Tomcat).
But what is the right way to unit test the Jersey resource classes (i.e., the classes that map to URLs)?
Do I need to have Tomcat running for this? Or should I mock the request and response objects, instantiate the resource classes in my tests, and feed the mocks to my classes?
I have read about testing in Jersey's site, but they're using Grizzly and not Tomcat in their examples, which is different.
Please explain how this should be done. Example code would be welcome.
If you just want to unit test, there's no need to start any server. If you have an services (business layer) or any other injections like UriInfo and things of that nature, you can just mock the. A pretty popular mocking framework is Mockito. Below is a complete example
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
/**
* Beside Jersey dependencies, you will need Mockito.
*
* <dependency>
* <groupId>org.mockito</groupId>
* <artifactId>mockito-core</artifactId>
* <version>1.10.19</version>
* </dependency>
*
* #author Paul Samsotha
*/
public class SomethingResourceUnitTest {
public static interface SomeService {
String getSomethingById(int id);
}
#Path("something")
public static class SomethingResource {
private final SomeService service;
#Inject
public SomethingResource(SomeService service) {
this.service = service;
}
#GET
#Path("{id}")
public Response getSomethingById(#PathParam("id") int id) {
String result = service.getSomethingById(id);
return Response.ok(result).build();
}
}
private SomethingResource resource;
private SomeService service;
#Before
public void setUp() {
service = Mockito.mock(SomeService.class);
resource = new SomethingResource(service);
}
#Test
public void testGetSomethingById() {
Mockito.when(service.getSomethingById(Mockito.anyInt())).thenReturn("Something");
Response response = resource.getSomethingById(1);
assertThat(response.getStatus(), is(200));
assertThat(response.getEntity(), instanceOf(String.class));
assertThat((String)response.getEntity(), is("Something"));
}
}
See Also:
How to get instance of javax.ws.rs.core.UriInfo
If you want to run an integration test, personally I don't see much difference whether or not you are running a Grizzly container vs. running a Tomcat container, as long as you are not using anything specific to Tomcat in your application.
Using the Jersey Test Framework is a good option for integration testing, but they do not have a Tomcat provider. There is only Grizzly, In-Memory and Jetty. If you are not using any Servlet APIs like HttpServletRequest or ServletContext, etc, the In-Memory provider may be a viable solution. It will give you quicker test time.
See Also:
junit 4 test case to test rest web service for some examples, aside from the ones given in the documentation.
If you must use Tomcat, you can run your own embedded Tomcat. I have not found much documentation, but there is an example in DZone. I don't really use the embedded Tomcat, but going of the example in the previous link, you can have something like the following (which has been tested to work)
import java.io.File;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.Response;
import org.apache.catalina.Context;
import org.apache.catalina.startup.Tomcat;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
/**
* Aside from the Jersey dependencies, you will need the following
* Tomcat dependencies.
*
* <dependency>
* <groupId>org.apache.tomcat.embed</groupId>
* <artifactId>tomcat-embed-core</artifactId>
* <version>8.5.0</version>
* <scope>test</scope>
* </dependency>
* <dependency>
* <groupId>org.apache.tomcat.embed</groupId>
* <artifactId>tomcat-embed-logging-juli</artifactId>
* <version>8.5.0</version>
* <scope>test</scope>
* </dependency>
*
* See also https://dzone.com/articles/embedded-tomcat-minimal
*
* #author Paul Samsotha
*/
public class SomethingResourceTomcatIntegrationTest {
public static interface SomeService {
String getSomethingById(int id);
}
public static class SomeServiceImpl implements SomeService {
#Override
public String getSomethingById(int id) {
return "Something";
}
}
#Path("something")
public static class SomethingResource {
private final SomeService service;
#Inject
public SomethingResource(SomeService service) {
this.service = service;
}
#GET
#Path("{id}")
public Response getSomethingById(#PathParam("id") int id) {
String result = service.getSomethingById(id);
return Response.ok(result).build();
}
}
private Tomcat tomcat;
#Before
public void setUp() throws Exception {
tomcat = new Tomcat();
tomcat.setPort(8080);
final Context ctx = tomcat.addContext("/", new File(".").getAbsolutePath());
final ResourceConfig config = new ResourceConfig(SomethingResource.class)
.register(new AbstractBinder() {
#Override
protected void configure() {
bind(SomeServiceImpl.class).to(SomeService.class);
}
});
Tomcat.addServlet(ctx, "jersey-test", new ServletContainer(config));
ctx.addServletMapping("/*", "jersey-test");
tomcat.start();
}
#After
public void tearDown() throws Exception {
tomcat.stop();
}
#Test
public void testGetSomethingById() {
final String baseUri = "http://localhost:8080";
final Response response = ClientBuilder.newClient()
.target(baseUri).path("something").path("1")
.request().get();
assertThat(response.getStatus(), is(200));
assertThat(response.readEntity(String.class), is("Something"));
}
}
Related
I am currently writing some unit tests for legacy code in a rest api application. One particular api call generates a list of URIs using the UriInfo api from Jax-RS. When I mock this interface, I am able to get the tests to run, but each call to the interface appears to reuse the same URI object and appends to it over and over, rather then a new URI object being passed to the tested code. I have a sample class with test that demonstates the issue:
import java.net.URI;
import java.util.LinkedList;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
#Stateless
#Path("/")
public class MockitoUrl {
#PersistenceContext(name = "MockitoTestPU")
private EntityManager em;
#Context
private UriInfo uriInfo;
#Path("system")
#GET
#Produces("text")
public List<URI> generateUris() {
List<URI> uris = new LinkedList<>();
for (int i=1;i<5;i++) {
final URI uri = uriInfo.getBaseUriBuilder().path(
MockitoUrl.class, "generateUris").build("test");
System.out.println(uri.toString());
}
return uris;
}
}
The unit test:
import java.net.URI;
import java.util.List;
import javax.persistence.EntityManager;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import static org.mockito.Mockito.when;
import org.mockito.MockitoAnnotations;
public class MockitoUrlTest {
#Mock
private EntityManager em;
#Mock
private UriInfo uri;
#InjectMocks
MockitoUrl mockitoUrl;
public MockitoUrlTest() {
}
#Before
public void setUp() {
mockitoUrl = new MockitoUrl();
MockitoAnnotations.initMocks(this);
}
#Test
public void testGenerateUris() throws Exception {
System.out.println("generateUris");
String baseUri = "http://server1/api";
when(uri.getBaseUriBuilder()).thenReturn(UriBuilder.fromUri(baseUri));
List<URI>result = mockitoUrl.generateUris();
for (URI u : result) {
assertTrue(u instanceof URI);
System.out.println(u.toString());
}
}
}
When the test is run, the output can be seen thus:
generateUris
http://server1/api/system
http://server1/api/system/system
http://server1/api/system/system/system
http://server1/api/system/system/system/system
What I would have expected is that it would return the same URI each time. In the real application these URIs would have more detail and each would have different data from a JPA class lookup. It seems that the same object is returned each time and then appended to again.
Is there a way to get Mockito to return a fresh URI each time uriInfo.getBaseUriBuilder() is called, or is this a fundamental misunderstanding I have about how Mockito works?
The problem you face is expected behavior. When setting up the mock you create a single instance and that is always returned.
To get what you want I would suggest using when(..).thenAnswer(i -> UriBuilder.fromUri(baseUri))
By this every call executes the provides lambda and it creates a new instance per invocation.
I am able to generate restdocs for rest services which is created by me, but unable to generate docs for services which i am consuming.
Is there any way to test and generate docs for third party API.
Sample code which i am using to generate to docs for local services.
#RunWith(SpringRunner.class)
#WebAppConfiguration
#SpringBootTest(classes = RestdocApplication.class)
public class CountryDocumentation {
private static final Logger logger =
LoggerFactory.getLogger(CountryDocumentation.class);
private MockMvc mockMvc;
#Autowired
private WebApplicationContext context;
#Rule
public final JUnitRestDocumentation restDocumentation = new
JUnitRestDocumentation("target/generated-snippets");
#Mock
private CountryService countryService;
#Mock
private RestTemplate restTemplate;
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).apply(documentationConfiguration(this.restDocumentation)
.uris().withHost("X.X.X.X").withPort(9090).and().operationPreprocessors()
.withResponseDefaults(prettyPrint())
.withRequestDefaults(prettyPrint())).defaultRequest(get("/")).build();
}
#Test
public void getCountryDefinition() throws Exception {
this.mockMvc.perform(get("/"))
.andExpect(status().is(200))
.andDo(document("{ClassName}/{methodName}"));
}
}
You've said in a comment that you want to mock the actual call to the remote service. I would argue that makes the documentation pointless. If your tests that generate the documentation are calling a mocked service, you're documenting the mock not the service. If you want the benefits of REST Docs' test-driven approach to documentation generation, your tests need to call the service that is being documented. If the service is only remotely accessible then you'll need to make HTTP calls to document it.
You can use Spring REST Docs with REST Assured or WebTestClient to document any service that's accessible via HTTP. Here's an example with REST Assured that documents part of Stack Exchange's API:
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.restdocs.JUnitRestDocumentation;
import static io.restassured.RestAssured.given;
import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document;
import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration;
public class RestAssuredExampleTests {
#Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
private RequestSpecification documentationSpec;
#Before
public void setUp() {
this.documentationSpec = new RequestSpecBuilder()
.addFilter(documentationConfiguration(this.restDocumentation))
.setBaseUri("https://api.stackexchange.com/2.2").build();
}
#Test
public void answers() throws Exception {
given(this.documentationSpec).accept(ContentType.JSON).filter(document("answers"))
.when().get("answers?order=desc&sort=activity&site=stackoverflow").then()
.assertThat().statusCode(200);
}
}
There are many products for mocking/virtualizing services. Including SoapUI and Parasoft Virtualize.
I am having trouble attaching a ContainerRequstFilter to a very simple JAX-RS rest application inside Glassfish4.
I believe that I've followed the instructions from both the javadoc and various other tutorial sources, but I am now at a complete loss.
The entire source (very short) is below, with the expected functionality:
(login) A user can log in at http://localhost/app/api/login/uname/password and the response is "You are logged in, uname"
(verify) User visits http://localhost/app/api/login/verify/uname and the response is a 401 unauthorized.
The second bit is meant the be implemented as a filter. What actually happens is that the first bit (login) works, and the second bit (verify) completely ignores the filter (including nothing in the logs to indicate that the filter ran). That is, the output is just "Every thing is fine, uname", rather than a 401 error.
What I want to understand is the way to get the filter attached to the verify action. For reference
I'm running glassfish 4.1 build 13
I'm compiling and deploying using gradle, with the deployment action
assassin deploy --force --contextroot /app /path/to/app.war
Glassfish reports that it's using Jersey 2.10.4
Here is the entirety of the source related to the application:
RestApp.java
package test.pack;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/api")
public class RestApp extends Application
{
#Override
public Set<Class<?>> getClasses()
{
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(Login.class);
return classes;
}
}
Login.java
package test.pack;
import javax.ejb.Stateless;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
#Stateless
#Path("login/")
#Produces("text/json")
public class Login
{
#GET
#Path("{username}/{password}")
public Response login(#PathParam("username") String username, #PathParam("password") String password)
{
System.out.println("Logging in");
return Response.ok("You are logged in, " + username).build();
}
#GET
#Path("/verify/{username}")
#Secured
public Response verify(#PathParam("username") String username)
{
System.out.println("Verify");
return Response.ok("Everything is fine, " + username).build();
}
Secured.java
package test.pack;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.ws.rs.NameBinding;
#NameBinding
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE, ElementType.METHOD})
public #interface Secured
{
}
LoggedInFilter.java
package test.pack;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Response;
#Secured
public class LoggedInFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
System.out.println("request");
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
}
Ugh. That's embarrassing.
The next tutorial I visited had the solution, which was to register the filter in the RestApp class.
RestApp.java
#ApplicationPath("/api")
public class RestApp extends Application
{
#Override
public Set<Class<?>> getClasses()
{
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(Login.class);
return classes;
}
#Override
public Set<Object> getSingletons()
{
Set<Object> singletons = new HashSet<Object>();
singletons.add(new LoggedInFilter());
return singletons;
}
}
I'll leave the answer here rather than deleting the question, since it was only in one of 4 tutorials that I read, and so this might be at least a little interesting.
I have a complicated scenario, for which i have no idea how to go about:
I have my ejbs running in a remote server.
And my web application running in a different server.
I have an ApplicationContext, that will differ based on domain, language, country etc.
I would like this application context to be passed to the remote EJB anonymously, in such a way that developers dont have to invoke all of their backend requests with the ApplicationContext as a parameter.
This is the scenarion, lets says i have a remote Stateless EJB:
#Stateless
public class MyStateless implements MyStatelessRemote{
//The application context that needs to be supplied form the front-end
#Inject //probably define a producer method to always supply a new one.
private ApplicationContext applicationContext;
public void doCheckSomething(final MySomethingData data){}
}
And on the frontend:
#SessionScoped
#Named
public class MyController implements Serializable{
#EJB
private MyStatelessRemote statelessRemote
//The current application/session context to be passed to the Stateless ejb on every invocation.
#Inject
private ApplicationContext executionContext;
public void doSomeOrderOrSomethingSimilar(){
//At this point, the current application context needs to be supplied to the remote EJB
//Which it may use to check on order validity based on configurations such as country
//language etc.
statelessRemote.doCheckSomething(mySomething);
}
}
With more than 20 EJBS and each having an average of 8 to 10 methods, and considering the likelihood that almost every ejb may need to know the executioncontext of the caller,
is it possible to parse the current execution context, through configuration or otherwise to the ejb during invocation of any method?
I am using Wildfly8 with remote ejb3.1, CDI1.1, JSF2.2
The application context may change when, for example the user changes his/her language
EDIT:
I am looking for something similar to Web Service inbound and outbound interceptors.
What you're describing is not possible using CDI/EJB, without passing in parameters to your remote EJB.
After few months working on jboss/wildfly server, i finally found a away to achieve this functionality:
Client-Side Code: (Based on jboss ejbclient)
package com.mycompany.view.service.wildfly.invocationcontext;
import com.mycompany.ejb.internal.MyCompanyAccount;
import com.mycompany.view.service.account.LoggedInAccount;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import org.jboss.ejb.client.AttachmentKey;
import org.jboss.ejb.client.EJBClientContext;
import org.jboss.ejb.client.EJBClientInterceptor;
import org.jboss.ejb.client.EJBClientInvocationContext;
import static com.mycompany.management.wildfly.invocationcontext.MyCompanyInvocationContextKey.MYCOMPANY_ACCOUNT_NUMBER;
/**
* Registers itself as a jboss client interceptor.
* #author marembo
*/
#Singleton
#Startup
public class MyCompanyInvocationContextInterceptor implements EJBClientInterceptor {
private static final Logger LOG = Logger.getLogger(MyCompanyInvocationContextInterceptor.class.getName());
private static final AttachmentKey<Long> MYCOMPANY_ACCOUNT_NUMBER_KEY = new AttachmentKey<>();
#Inject
#LoggedInAccount
private Instance<MyCompanyAccount> loggedInAccount;
#PostConstruct
void registerSelf() {
EJBClientContext.requireCurrent().registerInterceptor(0, this);
}
#Override
public void handleInvocation(final EJBClientInvocationContext ejbcic) throws Exception {
LOG.log(Level.INFO, "Intercepting invocation on: {0}", ejbcic.getInvokedMethod());
final EJBClientContext clientContext = ejbcic.getClientContext();
if (!loggedInAccount.isUnsatisfied()) {
final MyCompanyAccount mycompanyAccount = loggedInAccount.get();
if (mycompanyAccount != null) {
final Long accountNumber = mycompanyAccount.getAccountNumber();
clientContext.putAttachment(MYCOMPANY_ACCOUNT_NUMBER_KEY, accountNumber);
}
}
ejbcic.getContextData().put(MYCOMPANY_ACCOUNT_NUMBER, "348347878483");
ejbcic.sendRequest();
}
#Override
public Object handleInvocationResult(final EJBClientInvocationContext ejbcic) throws Exception {
return ejbcic.getResult();
}
}
On the server side, i register a global interceptor:
package com.mycompany.management.wildfly.extension;
import com.mycompany.management.facade.account.MyCompanyAccountFacade;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.EJBContext;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
/**
* Default interceptor does not require #Interceptor
* #author marembo
*/
public class MyCompanyInvocationContextReceiver {
private static final Logger LOG = Logger.getLogger(MyCompanyInvocationContextReceiver.class.getName());
#Resource
private EJBContext ejbContext;
#EJB
private MyCompanyInvocationContext mycompanyInvocationContext;
#EJB
private MyCompanyAccountFacade mycompanyAccountFacade;
#AroundInvoke
public Object setMyCompanyAccount(final InvocationContext invocationContext) throws Exception {
final Map<String, Object> contextData = ejbContext.getContextData();
LOG.log(Level.INFO, "EJBContext data: {0}", contextData);
LOG.log(Level.INFO, "InvocationContext data: {0}", invocationContext.getContextData());
return invocationContext.proceed();
}
}
and the ejb-jar.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee"
version = "3.1"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd">
<interceptors>
<interceptor>
<interceptor-class>com.mycompany.management.wildfly.extension.MyCompanyInvocationContextReceiver</interceptor-class>
</interceptor>
</interceptors>
<assembly-descriptor>
<interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>com.mycompany.management.wildfly.extension.MyCompanyInvocationContextReceiver</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
</ejb-jar>
As indicated on the server side interceptor, you can get the client-sent-data either from the InvocationContext or from the EJBContext.
I am trying to set up a Jersey ClientResponseFilter. It is working fine, but I want to deserialize my request parameters into a String so I can write helpful messages into a log file containing the actual data.
I was thinking about using MessageBodyWorkers for this. As this link below says:
"In case you need to directly work with JAX-RS entity providers, for example to serialize an entity in your resource method, filter or in a composite entity provider, you would need to perform quite a lot of steps."
Source: 7.4. Jersey MessageBodyWorkers API
This is exactly what I want to prevent.
So I was thinking about injecting the messagebodyworkers into my filter like this:
package somepackage.client.response;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.message.MessageBodyWorkers;
import org.slf4j.Logger;
#Provider
public class ResponseFilter implements ClientResponseFilter {
// TODO: these workers are not injected
#Context
private MessageBodyWorkers workers;
private final Logger logger;
public ResponseFilter(Logger logger) {
this.logger = logger;
}
#Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext)
throws IOException {
if (responseValid(responseContext)) {
return;
}
logger.error("Error", "Some param");
}
private boolean responseValid(ClientResponseContext responseContext) {
if (responseContext.getStatus() == HttpServletResponse.SC_OK) {
return true;
}
return false;
}
}
But the reference is always null and remains null. Note that this filter is running in a standalone application, no servlet container is available.
Why isn't the annotation working in this case? How can I make it work? Or if making this approach to work is impossible, how can I work around this?
Any suggestions?
OK. Here is the workaround solution for the problem above: we should use #Inject and the HK2 Dependency Injection Kernel
HK2 Dependency Injection Kernel Link
First we need to make some changes to the filter:
package somepackage.client.response;
import java.io.IOException;
import javax.inject.Inject;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import org.glassfish.jersey.message.MessageBodyWorkers;
import org.slf4j.Logger;
public class ResponseFilter implements ClientResponseFilter {
#Inject
private MessageBodyWorkers workers;
private Logger logger;
#Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext)
throws IOException {
if (responseValid(responseContext)) {
return;
}
logger.error("Error", "Some param");
}
private boolean responseValid(ClientResponseContext responseContext) {
if (responseContext.getStatus() == HttpServletResponse.SC_OK) {
return true;
}
return false;
}
public void setLogger(Logger logger) {
this.logger = logger;
}
}
As you can see the constructor changed, the class uses the default constructor, and the annotation changed to #Inject. Be aware that there are two #Inject annotations with the same name. Make sure you use: javax.inject.Inject.
Then we need to implement org.glassfish.hk2.utilities.binding.AbstractBinder:
package somepackage.client;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.message.MessageBodyWorkers;
import org.glassfish.jersey.message.internal.MessageBodyFactory;
public class Binder extends AbstractBinder {
#Override
protected void configure() {
bind(MessageBodyFactory.class).to(MessageBodyWorkers.class);
}
}
And finally we should register the filter and our binder in the client:
...
client.register(ResponseFilter.class);
client.register(new SitemapBinder());
...
Then the worker is going to be injected fine.