Open virajjasani opened 1 year ago
Currently, I am not aware of any projects that would use guice. The support should be handled by the guice-hk2 bridge as you mentioned, so perhaps it is more a question for the HK2 project. But maybe someone from the community has an experience with guice and will be able to help.
Thank you @jansupol, appreciate your comment. i have also tried using ResourceConfig as per the patch i mentioned above:
+
+ @Override
+ public void addJerseyResourceConfigs(HttpServer2 server) {
+ ResourceConfig resourceConfig = new ResourceConfig();
+ resourceConfig.packages(MyTestWebService.class.getPackage().getName() + ";"
+ + MyTestJAXBContextResolver.class.getPackage().getName());
+ resourceConfig.register(MyTestJAXBContextResolver.class);
+ resourceConfig.register(MyTestWebService.class);
+ server.addJerseyResourceConfig(resourceConfig, "/ws/v1/test", new HashMap<>());
+ }
});
however, it only helps instantiating MyTestJAXBContextResolver
(by jersey-hk2), which is ContextResolver for MyTestWebService
.
MyTestWebService is not executed when http call to /ws/v1/test
is made.
i am also curious why ContextResolver#getContext is not getting called.
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.google.inject.Singleton;
import org.apache.hadoop.yarn.webapp.resource.MyTestWebService.MyInfo;
@Singleton
@Provider
public class MyTestObjectWriterContextResolver implements ContextResolver<ObjectWriter> {
private ObjectWriter context;
private final Set<Class> types;
// you have to specify all the dao classes here
private final Class[] cTypes = { MyInfo.class };
public MyTestObjectWriterContextResolver() {
this.types = new HashSet<>(Arrays.asList(cTypes));
this.context = new ObjectMapper().writerFor(MyInfo.class);
}
@Override
public ObjectWriter getContext(Class<?> objectType) {
return (types.contains(objectType)) ? context : null;
}
}
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.hadoop.http.JettyUtils;
@Path("")
public class MyTestWebService {
@GET
@Produces({ MediaType.APPLICATION_XML + "; " + JettyUtils.UTF_8 })
public MyInfo get() {
return new MyInfo();
}
@XmlRootElement(name = "myInfo")
@XmlAccessorType(XmlAccessType.FIELD)
public static class MyInfo {
public MyInfo() {
}
}
}
ResourceConfig resourceConfig = new ResourceConfig();
resourceConfig.register(MyTestObjectWriterContextResolver.class);
resourceConfig.register(MyTestWebService.class);
server.addJerseyResourceConfig(resourceConfig, "/ws1/v1/test/*", new HashMap<>());
the implementation of addJerseyResourceConfig:
protected final WebAppContext webAppContext;
...
...
...
/**
* Add a Jersey resource config.
* @param config The Jersey ResourceConfig to be registered.
* @param pathSpec The path spec for the servlet
* @param params properties and features for ResourceConfig
*/
public void addJerseyResourceConfig(final ResourceConfig config,
final String pathSpec, Map<String, String> params) {
LOG.info("addJerseryResourceConfig: pathSpec={}", pathSpec);
final ServletHolder sh = new ServletHolder(new ServletContainer(config));
for (Map.Entry<String, String> entry : params.entrySet()) {
sh.setInitParameter(entry.getKey(), entry.getValue());
}
webAppContext.addServlet(sh, pathSpec);
}
Here, when GET endpoint ws1/v1/test
is called, somehow MyTestObjectWriterContextResolver#getContext
is not even getting executed.
ContextResolver
is not invoked by default; you need something like
@Context
Providers providers;
public ObjectWriter getObjectWriter(Class<?> objectType) {
ContextResolver<ObjectWriter> ctx = providers.getContextResolver(ObjectWriter.class, MediaType.APPLICATION_XML_TYPE);
return ctx.getContext(objectType);
}
in your provider.
For the record, here is the documentation for HK2 - Guice bridge.
As part of migrating Jersey from 1.19.4 to 2.39.1, we are facing some issues with guice bind.
Here is the draft PR: https://github.com/apache/hadoop/pull/5768
All updated dependencies are defined here: https://github.com/apache/hadoop/pull/5768/files#diff-df2aa66a3757d73c93849b3a279d42a4634b0aed3550cdd2ead32d2fa06bf49e (hadoop-project/pom.xml)
We have a test TestWebApp https://github.com/apache/hadoop/blob/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/webapp/TestWebApp.java#L245
The idea here is to ensure that custom routes are served with the above mentioned endpoints.
Moreover, MyTestJAXBContextResolver and MyTestWebService are used to bind requests starting with "ws/v1/test".
The changes done for MyTestJAXBContextResolver: https://github.com/apache/hadoop/pull/5768/files#diff-52936fdf3657b9acf3cffa439cf5c0b71737d51d8d473329843e66ca462aa306
and MyTestWebService (without changes): https://github.com/apache/hadoop/blob/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/webapp/MyTestWebService.java
Since guice bind is not able to bind the classes,
getResponseCode(baseUrl + "ws/v1/test")
always results into 404.i have also tried adding the classes/packages with ResourceConfig but it is only able to instantiate MyTestJAXBContextResolver, it is still not able to redirect
ws/v1/test
GET to MyTestWebService.guice-hk2 is in the classpath. the test belongs to hadoop-yarn-common module.
Edit: additional reference: we create embedded Jetty server to server http requests in HttpServer2 Changes for the class in the PR: https://github.com/apache/hadoop/pull/5768/files#diff-4e9d7dccc4530205e71b54fe7f967135aeca170cff5ace98b5b7f04304153813