I have a code:
return Response.status(Status.BAD_REQUEST).entity(errors).build();
Where: Response is comes from this package: javax.ws.rs.core (jersey 1.9.1);
Where the errors is instance of:
#XmlRootElement
public class UserInfoValidationErrors {
#XmlElement String username;
#XmlElement String email;
...
Then I have JSON result like this: {"username":null,"email":"Email is not valid"}
If there is a way how to avoid having null there?
If you have Jersey configured to use Jackson to do it's JSON serialization, you can annotate your model classes with:
#JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
If you want to configure Jersey to use Jackson, you can update your web.xml as follows:
<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-value>com.your.package;org.codehaus.jackson.jaxrs</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Use #XmlElement(nillable = true). At least this works for XML generation, so I believe it should work for JSON as well.
Related
I'm using Jersey and I implemented a ContainerRequestFilter.
Now I also want to add a ContainerResponseFilter to add a header to each request but nothing happens when the webservice is accessed.
This is how the filter looks like:
public class ResponseFilter implements ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
MultivaluedMap<String, Object> headers = responseContext.getHeaders();
headers.add("Cache-Control", "whatever");
}
}
My jersey dependencies:
compile 'org.glassfish.jersey.core:jersey-client:2.18'
compile 'org.glassfish.jersey.containers:jersey-container-servlet-core:2.18'
compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.18'
I register the providers in an xml like this:
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>controller.webservice</param-value>
</init-param>
//This is the request filter, which is working fine
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>model.filter.AuthenticationFilter</param-value>
</init-param>
//Response filter, does not work
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>model.filter.ResponseFilter</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
This didn't work, so I tried to register the provider with the annotation #Provider and in the webservice like this:
register(TokenModifier.class);
But none of these worked. I read several other posts but I couldn't find an answer to it. Does anyone have a thought on this?
This init-param
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>controller.webservice</param-value>
</init-param>
is used by Jersey to scan package(s) listed for #Path and #Provider annotated classes, and register them. The package(s) listed will be recursively scanned. So for example, with your current configuration, all the following packages will get scanned
controller.webservice
controller.webservice.x
controller.webservice.x.y
controller.webservice.x.y.z
The value of the param can also be multiple values separated by a comma or semi-colon. So if your filter is in a different package base, you can add that package to the list of packages to scan
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>controller.webservice, com.my.filters</param-value>
</init-param>
Personally though, if I'm using web.xml, I will just use one base package, and have all other packages extend from that package. Something like
com.company.app
com.company.app.domain
com.company.app.filters
com.company.app.resources
Then you can just put the com.company.app as the init-param value, and all other sub packages will get scanned also.
I'trying to create simple WS project in Spring and Spring WS without any XSD. Deploy on jetty.
Is possible to populate WS endpoint and generate WSDL only from java classes (no static XSD or WSDL - I went throught many tutorials but all requiered).
For any help, hint or link highly appreciated.
I have something like this:
1) Request
#XmlRootElement
public class MessageWSRequest {
#XmlElement
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
2) Endpoint
#Endpoint
public class MessageWS {
#PayloadRoot(namespace = "http://message.com/ws/message" ,localPart="MessageWSRequest")
public String handleMathServiceRequest(#RequestPayload MessageWSRequest messageWSRequest) {
return "ok";
}
}
3) springContext.xml
<sws:annotation-driven/>
<context:component-scan base-package="com.ws.message"/>
4) web.xml
<servlet>
<servlet-name>webservices</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>webservices</servlet-name>
<url-pattern>*.wsdl</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>webservices</servlet-name>
<url-pattern>/endpoints/*</url-pattern>
</servlet-mapping>
Now I would expect URL like this
localhost:8080/messageTest/endpoints/MessageWS.wsdl
with generated WSDL.
Did I miss some configuration or so?
Thanks all
Ok, next day a clear mind revelead me this fact:
Spring WS offers "only" contract-first, starting from an XSD Schema
I'll use CXF instead:
Apache CXF offers both contract-last (starting with Java) and Contract-first (starting with the WSDL) approaches.
As you have noted, Spring WS is designed for contract first services. However I think that you can still achieve what you want to do if you generate the XSD during the build process from your annotated classes. Here is one way to do that:
Generating XSD schemas from JAXB types in Maven?
I recently set up RESTEasy on Tomcat 7. We do not use Maven. I mention this early on, because all of the answers I've found to my question to date suggest adding a reference to the pom.xml. Adding references to my project, so far, hasn't solved my problem (but, maybe I'm missing something).
At this point, I'm just trying to recreate the out-of-the-box examples I've seen online where I should be able to correctly annotate a POJO, and return it as JSON using RESTEasy, assuming I have my build configured correctly. My build references:
- jackson.core.asl
- jackson.jaxrs
- jackson.mapper.asl
and all the required RESTEasy jars. In fact, I can successfully obtain the JSON I want from a GET if I return a Response (as in the example I found here: RestEasy: Could not find MessageBodyWriter for response object of type: java.util.ArrayList of media type: application/json). Of course, that's not using Jackson through RESTEasy, at all.
Whenever I try to return an object, however, of any kind, I get:
Could not find MessageBodyWriter for response object of type: ... application/json
I'm not sure what I'm doing wrong, as all the answers I can find suggest that what I need to do is make sure that jackson is correctly referenced---which, from all I can tell, it is. Below is the relevant portion of my web.xml.
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>rest_services.RootRestService</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/services</param-value>
</context-param>
Here is my Service method:
#GET
#Path("/getTables")
#Produces(MediaType.APPLICATION_JSON)
public List<MyTable> getTables() {
...
}
Here is the class it's returning:
#XmlRootElement
public final class MyTable {
...
}
EDIT :
Here are the classes I added to my classpath (and a few others)
:
Any help is greatly appreciated.
I was never able to get Jackson working, but I switched to Jettison, and all works fine. This is good enough for me, for now.
I have
#ApplicationPath("/resourcesP")
public class RestfulPrediction extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> set = new HashSet<Class<?>>();
set.add(PredictionsRS.class);
return set;
}
}
And
#ApplicationPath("/resourcesA")
public class RestfulAdage extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> set = new HashSet<Class<?>>();
set.add(Adages.class);
return set;
}
}
Two different ApplicationPath and the class are as follows.
#Path("/")
public class service.Adages {}
#Path("/")
public class webservices.PredictionsRS {}
Both of them are declared in different ApplicationPath. I'm using Jersey and the config in web.xml looks like
<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-value>
service
webservices
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
And I'm getting
SEVERE: Conflicting URI templates. The URI template / for root
resource class service.Adages and the URI template / transform to the
same regular expression (/.*)?
Why if I have two different ApplicationPath this exception comes at startup ?
If I take out a package in param-value this works, also if I change one of the #Path annotations this works, so it is a problem with my configuration ?
I'm using Jersey 1.10. Thanks all.
You did not define your JAX-RS applications in your web.xml. Try the following:
<servlet>
<servlet-name>full.name.RestfulAdage</servlet-name>
</servlet>
<servlet>
<servlet-name>full.name.RestfulPrediction</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>full.name.RestfulPrediction</servlet-name>
<url-pattern>/resourcesP/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>full.name.RestfulPrediction</servlet-name>
<url-pattern>/resourcesA/*</url-pattern>
</servlet-mapping>
and remove the #ApplicationPAth annotations from code.
I checked the above code with Jersey 2.7, servlet container 3.0 and it works. If still having that bug, try upgrading to Jersey 1.17 (which should not change any behavior from Jersey 1.10, and fix bugs instead) and eventually using also a servlet container 3.0.
UPDATE
After checking the possibilities the configuration below work with Jersey 1.17
<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-value>
com.koitoer.webservices
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
It seems there is bug in the spec in older version of Jersey that kind of circle back the references and mark as duplicate endpoints. Using the configuration above both endpoints load without any problem.
8/04/2014 09:13:40 PM
com.sun.jersey.server.impl.container.servlet.JerseyServletContainerInitializer
addServletWithApplication INFO: Registering the Jersey servlet
application, named com.koitoer.webservices.chapter2.service2.RestfulPrediction, at the
servlet mapping, /resourcesP/*, with the Application class of the same
name
8/04/2014 09:13:40 PM com.sun.jersey.server.impl.container.servlet.JerseyServletContainerInitializer
addServletWithApplication INFO: Registering the Jersey servlet
application, named com.koitoer.webservices.chapter2.RestfulAdage, at
the servlet mapping, /resourcesA/*, with the Application class of the
same name
You should have a single subclass of javax.ws.rs.core.Application in your webapp, and then use different #Path annotation values on your service.Adages and webservices.PredictionsRS resource types.
AFAIK, in JEE6 containers, you are not allowed to have 2 such subclasses...
How to pass pojo object as parameter to rest web service from prototypejs client.
Assume i have web service like this.
#Path("/postItem")
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Item postItem(Item item)
{
return new item;
}
From client side using prototypejs library how to pass pojo object as parameter to rest web service.
If parameter is of type string or integer i would have passed it as query param but it is pojo object in case.
I am about the syntax creation of the pojo object and then passing it to rest web service from prototypejs.
Which jax-rs implementation do you use? for Jersey, you can post json to the server by specify the jersey servlet:
<servlet>
<servlet-name>jersey-servlet</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-value>your package</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>/api/*</url-pattern>
</servlet-mapping>
then in your client code, you can directly post a json to the server, which will be deserialized to an Item instance