I am following this article to make our Jersey to CORS complaint. So far I have implemented ContainerResponseFilter to add Access-Control-Allow-Origin headers to response. This is my snippet:
ResponseBuilder resp = Response.fromResponse(contResp.getResponse());
resp.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
String reqHead = req.getHeaderValue("Access-Control-Request-Headers");
if(null != reqHead && !reqHead.equals("")){
resp.header("Access-Control-Allow-Headers", reqHead);
}
contResp.setResponse(resp.build());
And this is my web.xml contents:
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>com.test.ResponseCorsFilter</param-value>
</init-param>
When I run I get this error:
com.sun.jersey.spi.inject.Errors$ErrorMessagesException
com.sun.jersey.spi.inject.Errors.processErrorMessages(Errors.java:170)
com.sun.jersey.spi.inject.Errors.postProcess(Errors.java:136)
But if I run the same application with these config:
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.test.client</param-value>
</init-param>
I am not getting any error. So this error is occuring only if I try to use ContainerResponseFilter. Can someone help me in resolving this issue?
Related
I want to have a documentation for my REST-Calls, in a earlier Project I written it alone but now the Project is a bit bigger so I searched for a good framework. I found swagger.io. It looks very nice and the implementation looks very simple for the maven project. I set the dependency in the Path
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.0</version>
</dependency>
and configure the servlets of the web.xml
<servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
io.swagger.jaxrs.listing,
package.rest
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Jersey2Config</servlet-name>
<servlet-class>io.swagger.jersey.config.JerseyJaxrsConfig</servlet-class>
<init-param>
<param-name>api.version</param-name>
<param-value>0.0.1</param-value>
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>http://localhost:8080/rest</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
I think I have done it but after a new Maven Install and start the Jetty Server, I called the url localhost:8080/rest/swagger.xaml or ../swagger.json there comes the following Exception:
2016-07-08 09:13:12.058:WARN:oejs.ServletHandler:Error for /rest/swagger.json
java.lang.NoSuchMethodError: org.glassfish.jersey.internal.util.collection.Values.lazy(Lorg/glassfish/jersey/internal/util/collection/Value;)Lorg/glassfish/jersey/internal/util/collection/Value;
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:501)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:370)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:971)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1033)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:644)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:667)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:745)
Do you can help me?
I tried the install guide if swagger.io also for Jersey 1.17.1 there comes no exception but also no result.
The java.lang.NoSuchMethodError above is stemming from having different versions of Jersey 2 jars in your classpath.
See NoSuchMethodError on Values.lazy (Jersey 2.5.1) and https://java.net/jira/browse/JERSEY-2394 for more details.
I have found a few questions like this on SO already but none of them seemed to address my particular problem, and I have been unable to find a solution on my own.
Here is the error I'm getting:
Caused by: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=multipart/form-data; boundary=----WebKitFormBoundaryHWk1XUaeu7pEiDth, type=class org.glassfish.jersey.media.multipart.FormDataMultiPart, genericType=class org.glassfish.jersey.media.multipart.FormDataMultiPart.
I am sending this through a jQuery AJAX request that looks like this:
$('#upload-image-form').on('submit', function(e) {
e.preventDefault();
var data = new FormData(this);
$.ajax({
url: url,
method: 'POST',
contentType: false,
processData: false,
data: data,
}).done(function(data) {
console.log(data);
}).fail(function(res, status) {
onError(res, status, 'Image upload failed');
});
});
And this is my Java endpoint:
#POST
#Path("/{userId}")
#Consumes("multipart/form-data")
public Response createGraphic(
#PathParam("userId") int userId,
FormDataMultiPart multiPartFormData) { ... }
I have seen a few people have luck with changing the parameter of the endpoint method to use #FormDataParam instead of FormDataMultiPart (as seen here), but I cannot edit the Java class, so I must use it how it is above.
My pom.xml has the following dependencies:
<dependency>
<groupId>org.jvnet</groupId>
<artifactId>mimepull</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.12</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.12</version>
</dependency>
web.xml
<servlet>
<servlet-name>Jersey</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>my.package</param-value>
</init-param>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
The only other thing I was able to dig up was to register the MultiPartFeature using a ResourceConfig; however, the project I'm working with does not have any Application classes or any class that extends ResourceConfig (it's a WAR that's deployed to Tomcat, so no main class).
Is there any other configuration that needs to be done? I'm stumped as to why this is not working.
The MultiPartFeature has the required reader and writer. But you still need to register the feature. As you've mentioned, you will often see it's registration in an Application/ResourceConfig subclass. But in a web.xml, you can simply add it to the list of classes to add as provider. You can do that by adding an <init-param> to the servlet configuration, i.e.
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
org.glassfish.jersey.media.multipart.MultiPartFeature,
some.other.Provider
</param-value>
</init-param>
As you can see in the example, if you need to register any other providers/features, you comma-delimit the class names.
I am trying to introduce Jersey web service into a web application that has other web services (such as Apache CXF in it) in it. So I added Jersey servlet to my web.xml..
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>
com.sun.jersey.spi.spring.container.servlet.SpringServlet
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.freedomoss.crowdcontrol.api</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
During intiliazation this servlet gives the following error about conflicting URL templates...
INFO: Registering Spring bean, restApiService, of type com.mycompany.ws.RestApiService as a root resource class
Mar 12, 2015 11:07:42 PM com.sun.jersey.spi.spring.container.SpringComponentProviderFactory registerSpringBeans
SEVERE: The following errors and warnings have been detected with resource and/or provider classes:
SEVERE: Conflicting URI templates. The URI template / for root resource class com.mycompany.ws.RestApiService and the URI template / transform to the same regular expression (/.*)?
When I look in the code of this RestApiService, I see..
#Path("/")
#Service
public class RestApiService extends AbstractRestService {
Since this other web service is being used elsewhere in the application I cannot change the value of 'Path' although doing so does solve my problem
What else can I do? Can I somehow tell Jersey Servlet not to register this other web service "as a root resource class"?
My goal is to make Jersey work along with this other web service and not change the latter in any way.
I have a simple RESTful Java web service...
#Service
#Path("/getAccountBalance")
public class GetAccountBalanceService {
#Autowired
private ILicenseService licenseService;
#GET
#Path("/{param}")
public Response provideService(#PathParam("param") String licenseUUID) {
License license = this.licenseService.getByUUID(licenseUUID);
String output = "Balance on the account : " + license.getBalanceValue();
return Response.status(200).entity(output).build();
}
At first I was getting an error where the bean licenseService was null even though I am autowiring it. So based on advice from another post I swtiched to use the Spring servlet for jersey, thus in my web-xml I changed from com.sun.jersey.spi.container.servlet.ServletContainer to...
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>
com.sun.jersey.spi.spring.container.servlet.SpringServlet
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.freedomoss.crowdcontrol.api</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
But now when I start Tomcat I am getting the error..
Dec 19, 2014 12:13:13 AM org.apache.catalina.startup.ContextConfig applicationWebConfig
SEVERE: Parse error in application web.xml file at jndi:/localhost/mturk-web/WEB-INF/web.xml
java.lang.IllegalArgumentException: Servlet mapping specifies an unknown servlet name jersey-serlvet
Why is this happening? As you can see there is a servlet defined with that name in web-xml. If there was something wrong with loading that servlet why don't the logs tell that story?
Thanks.
I am using Jersey for my web service, and this is how my web.xml looks like:
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-name>com.rohanprabhu.external.interfaces.service.web</param-name>
</init-param>**
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-name>true</param-name>
</init-param>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey</servlet-name>
<url-pattern>*</url-pattern>
</servlet-mapping>
</web-app>
I am getting an error Occurred at line 10 column 22, which is where I have marked in my file as '**' (it isn't actually there in the file, I just put it on here). Here is (a part) of the stack trace I get:
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54)
at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35)
at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
Caused by: java.lang.IllegalArgumentException: Can't convert argument: null
at org.apache.tomcat.util.IntrospectionUtils.convert(IntrospectionUtils.java:889)
at org.apache.tomcat.util.digester.CallMethodRule.end(CallMethodRule.java:476)
at org.apache.tomcat.util.digester.Digester.endElement(Digester.java:1057)
... 188 more
Occurred at line 10 column 22
Marking this application unavailable due to previous error(s)
Here is the entire stacktrace, in case that helps: http://pastebin.com/EX4bMGex
I agree the error message is suboptimal, but I'm also sure you want one <param-name> and one <param-value> per <init-param>. :-)
You are using <param-name> twice. but other init attribute should be <param-value>.