I have a rest service written using Spring and CXF. The method is shown below.
#POST
#Path("/detail")
public StudentResponse getStudentDetails(Student student);
The Student Class.
#XmlRootElement(name="Student")
public class Student implements Serializable{
...
I am able to call the service using a cxf client
WebClient client = WebClient.create("http://localhost:8180/oauthserver/service/student/detail");
client.type("application/json").accept("application/json");
Response response =client.post(s);
StudentResponse sr = response.readEntity(StudentResponse.class);
The data i am posting(Used jackson to generate the json entry)
{
"name" : "input",
"id" : 1,
"marks" : 20.2
}
But while calling the service from PostMan for SoapUI i am getting the below error.
JAXBException occurred : unexpected element (uri:"", local:"name").
Expected elements are <{}Student>.
unexpected element (uri:"", local:"name"). Expected elements are <{}Student>.
I am calling as POST method and context type RAW.I have set the header values to this:
Content-Type : application/json
Accept : application/json
But still its not working. Any pointers?
Just posting this for any one facing the same issue.
I had to add the jackson provider to the service listing
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />
</jaxrs:providers>
then needed to add the maven dependency (The newer version will have a different package dependency)
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
This page had the solution...
http://cxf.apache.org/docs/jax-rs-data-bindings.html
Related
When I send an HTTP post request to spring boot rest API from my angular application, request is failing with below error
Browser Error
HTTP Status 415 – Unsupported Media Type
Type Status Report
Description: The origin server is refusing to service the request because the payload is in a format
not supported by this method on the target resource
Spring boot console error
java.lang.IllegalArgumentException: No converter found for return value of type: class java.util.LinkedHashMap
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:187) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:203) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
.......
What I have tried so far
As this solution mentioned, i have added the necessary headers to the request from angular end
this.http.post(ipUrl, args, { headers: new HttpHeaders({'Content-Type': 'application/json', 'Accept': 'application/json', 'Access-Control-Allow-Headers': 'Content-Type'})});
As this answer, I have added getters/setters to the Model objects
I want to know where i went wrong and how to resolve this issue?
UPDATE
Springboot Rest Controller method
#PostMapping("/login")
public #ResponseBody ResponseWrapper<WebUser> login(#RequestBody LoginData loginData){
try {
return loginService.loginProcess(loginData);
}
catch (Exception ex){
ProgrammerAlert.printStackTrace(ex);
return new ResponseWrapper<>(ResponseWrapper.ERROR, ex.getMessage());
}
}
Could you write your controller in this way. and see if it responds.
#ResponseBody
#RequestMapping(value = "/login",
method = RequestMethod.POST)
public ResponseWrapper<WebUser> login(...){
.
.
.
}
Is there a reason that you do not want to use RequestMapping ?
Is there any reasons not to add produces and consumes properties?
#PostMapping("/login", produces = MediaType.APPLICATION_JSON_UTF8, consumes = MediaType.APPLICATION_JSON_UTF8)
public #ResponseBody ResponseWrapper<WebUser> login(#RequestBody LoginData loginData){
try {
return loginService.loginProcess(loginData);
}
catch (Exception ex){
ProgrammerAlert.printStackTrace(ex);
return new ResponseWrapper<>(ResponseWrapper.ERROR, ex.getMessage());
}
}
or,
Did you add any JSON message converter, like jackson? Check your application has below dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
your return object should be converted to JSON properly. Add Jackson to you pom (separately from starter web) and retry.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
As per your recent edit, you're now getting 406 Not Acceptable, to fix this error, keep the media type of your Spring boot application's response same as the Accept header of your client. Try the following.
Change the value of produces to MediaType.APPLICATION_JSON as you have accept header in client as "application/json". Also please note:
APPLICATION_JSON_UTF8 is deprecated in favor of APPLICATION_JSON
Reference: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/MediaType.html
For those who are facing a similar issue, you can also check if there is any typo in Accept header as I often face this problem.
I also came across the same issue, I guess the answer of this question is very clear
HTTP Status 415 – Unsupported Media Type
while sending the request make the content type json instead of text
#RestController
#RequestMapping(value="/uri",produces = "application/json",
consumes="application/json")
public class VisitorService {
VisitorDAO vis=new VisitorDAO();
#RequestMapping(value = "/ex" ,method = RequestMethod.POST)
public String showDetails(#RequestBody VisitorDTO visitor){
vis.addVisitorEntry(visitor);
return "success"+visitor;
}}
Above is my rest service.
whenever I hit a post using the URL with the below JSON,
{
"phoneNumber" : 188892,
"name" : "kikiki" ,
"email" : "loa#gmail.com",
"purpose" : "Business",
"hostName" : "sjs S Murthy"
}
im getting HTTP Status 415 – Unsupported Media Type.
why would that be?
Check that you have set the #EnableWebMvc annotation in a #Configuration class.
Also, try adding the following dependencies to your pom.xml (if not using Maven, just add them to your classpath however you prefer).
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version> // 2.4.3
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version> // 2.4.3
</dependency>
Spring uses Jackson and Jackson-databind to parse the request's JSON body into a Java Object.
My curl request like below.
$ curl -ki -X POST -H "Content-Type:application/json;charset=utf-8" localhost:8081/Customers-Spring-MVC-Hibernate/customer -d '{"name": "anil","age": 1,"phoneNumber": 77955,"email": "pvv.anilkumar#gmail.com","password": "Password"}'
where i have given the content-type:application/json but i hit 415 status code.
Here is the response i got and i could see that Content-Type:text/html is being set is it proper here..?
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 1097
Date: Wed, 16 Nov 2016 05:29:27 GMT
Here is my controller definition:
#RequestMapping(method = RequestMethod.POST)
public void addCustomer(
#RequestBody final CustomerV1 customerDto) throws Exception
{
Please let me know if any workarounds..
i have tried removing and adding the charset-utf-8 but no use i still hit 415.
Adding my DTO definition if any problems here..
JSON DTO:
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonTypeName("customer")
public class CustomerV1 {
private String name;`enter code here`
private int age;
private long phoneNumber;
private String email;
private String password;
Try adding headers on your handler method as follows,
#RequestMapping(value="/add", method = RequestMethod.POST)
public void addCustomer(
#RequestBody final CustomerV1 customerDto) throws Exception
{
//your code
}
From your Github link I see that you are missing following entry in your spring-mvc-demo-servlet.xml file,
Also please look documentation : http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.html
With this you don't need to explicitly configure JSON as your consumption.
<!-- Configure bean to convert JSON to POJO and vice versa -->
<beans:bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
<!-- Configure to plugin JSON as request and response in method handler -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonMessageConverter"/>
</list>
</property>
</bean>
After the Heavy analysis and brain wreck i was able to figure out what the problem is ..
Primarily if any one is facing the same above problem like hitting 415 error...
first check on the content-types of the rest request .. it can be one of the probable root cause for the issue.. Please have a look at the below curl request for on the content-types..
curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d'{"name":"anil","age":2,"email":"anilmar.pvv","password":"anilkumar"}'http://localhost:8080/MySpringMvc/customer/add
if all the content-types are proper then lies the problem with the Jackson-jars that you have downloded..my best suggestion is to remove all the jars that you have downloaded prior you face the issue 415 and try to be constant through out the versions of the Jars.. below are the version that i have made constant and major 3 dependencies that are needed for the smooth execution please ensure that you have all the 3 jars of same version ensure that those are on the class-path..then it should work fine..below is the dependency jars that i have used and came out of the maze problem.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.5</version>
So I recently moved from Jersey 1.x to 2.x and after a long list of problems finaly got it working. But whenever I try to reach a resource which returns a JSONObject I get problems. First of, here is my example method:
#GET
#Path("/foobar")
#Produces(MediaType.APPLICATION_JSON)
public JSONObject print2() throws JSONException {
JSONObject jsonObject = new JSONObject();
jsonObject.put("hi", 22);
return jsonObject;
}
Now if I use Jettison 1.3.8 for my JSONObject, I get the following if I try to reach this resource:
{"escapeForwardSlashAlways":true}
Not sure whats going on there. Then I tried some older versions of Jettison and also the org.json but these gives me this issue instead:
No serializer found for class org.json.JSONObject and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )
Not sure why I get these problems when this kind of method worked fine for me on Jersey 1.x.
Assuming you are using Servlet 3.0 and above, the following example might help you to setup your environment to work with JSON data:
Dependency: if you are using Maven you need the following dependencies:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.23.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.23.2</version>
</dependency>
If you are not using Maven, you need to add the correponding jars into your classpath.
Define POJOs to contain the data you want to serialize to JSON, for example,
public class User {
private String username;
private String email;
// getters + setters
}
Modify your resource method accordingly:
#GET
#Path("/foobar")
#Produces(MediaType.APPLICATION_JSON)
public User print2() {
User jsonObject = new User();
jsonObject.setUsername("Me");
jsonObject.setEmail("my#email.com");
return jsonObject;
}
Package and deploy, and the output should be:
{
"username": "Me",
"email": "my#email.com"
}
Note: This example is deployed and works on Tomcat 8.5.5.
I was struggling with the same issue, and eventually Jersey's bookmark exmple helped.
The problem is that your Jersey has no serializer for JSONObject and it tries to use BeanSerializer instead. Jettison JSONObject has only one public getter (isEscapeForwardSlashAlways) and org.json.JSONObject has no getters at all so BeanSerializer cannot be applied.
The solution is for (jettison json object):
Add dependency jersey-media-json-jettison:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jettison</artifactId>
<version>2.26</version>
</dependency>
Register the jettison feature declaratively in your web.xml
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.jettison.JettisonFeature</param-value>
<init-param>
Or programmatically in your application:
#ApplicationPath("/")
public class MyApplication extends ResourceConfig {
public MyApplication() {
registerClasses(UsersResource.class);
register(new JettisonFeature());
}
}
web.xml:
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.glassfish.jersey.examples.bookmark.MyApplication</param-value>
</init-param>
Perhaps org.json.JSONObject has such serializer feature for Jersey too, I don't know...
Another option is to allow the Response to convert your object to JSON. This gives the added benefit of adding the HTTP code as well. So you can return a 400, 404, 500 etc. and still send back a JSON response that can be acted upon by your JS. You should be able to drop your JSONObject in there since it's basically just extended Map - or any object for that matter.
#GET
#Path("/foobar")
#Produces(MediaType.APPLICATION_JSON)
public Response print2() {
User jsonObject = new User();
jsonObject.setUsername("Me");
jsonObject.setEmail("my#email.com");
return Response.status(Response.Status.OK).entity(jsonObject).build());
}
I am trying to save data on my database with a web service POST wich serializes a HTML form to save a object. The rest client firefox says this:
"The server refused this request because the requested entity is in a format not supported by the requested resource for the requested method"
The eclipse console shows the message:
org.jasig.cas.client.util.CommonUtils - safeGetParameter called on a POST HttpServletRequest for LogoutRequest. Cannot complete check safely. Reverting to standard behavior for this Parameter
I understand that the object that i want to save is not valid, but I don't see what the problem is.
#RequestMapping(value="/solicitudCita", method = RequestMethod.POST)
public #ResponseBody String putSolicitud(#ModelAttribute("Solicitud") Solicitud solicitud) throws Exception{
System.out.println(solicitud.toString());
solicitudCitaAppMService.createOrUpdate(solicitud);
String solicitudAdded = "Solicitud de cita -> {" + solicitud.toString() + "} añadida";
System.out.println(solicitud);
return solicitudAdded;
}
Help me please
Thanks
If you want to call this controller in a RESTful manner, you have to annotate the solicitud parameter as #RequestBody. Second, you have to have the Jackson libraries in you classpath so Spring can pick them up and use them for unmarshalling the object.
If you use Maven, use these dependencies:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.12</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.12</version>
</dependency>
BTW, why do you have to serialize the HTML form and sent it across? I would suggest you use a REST client, for instance this one, that is available in the Chrome WebStore.