Post data Spring web services Restful - java

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.

Related

Cannot send http post request to springboot

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

Javax Jersey client processingException

I have a Maven jersey server that sends json objects to my JavaFX client, in my server I have model classes that have strings and int and in the client model class I tried to use Stringproperty and IntegerProperty (for the bind use and I have proper getter and setters(setter = name.set("example"),
getter = return name.get)) but when I do I get
Both front and backend have JSON as mediatype and when I change client modelclass variables to String and Int everything works as expected.I want to find a way to keep the property of strings and int for the bind method, I tried to google but no one else seems to have had this problem, does anyone know what can solve this and let me use property of variables
I caught the exception as
processingException e
e.getCause(): null
e.getMessage():
MessageBodyReader not found for media type=application/json, type=interface java.util.List, genericType=java.util.List<models.Users>.
[org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:207), org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:139), org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1109), org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:853), org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:812), org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:309), org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:813), org.glassfish.jersey.client.JerseyInvocation.access$600(JerseyInvocation.java:90), org.glassfish.jersey.client.JerseyInvocation$3.call(JerseyInvocation.java:693), org.glassfish.jersey.internal.Errors.process(Errors.java:315), org.glassfish.jersey.internal.Errors.process(Errors.java:297), org.glassfish.jersey.internal.Errors.process(Errors.java:228), org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:422), org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:689), org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:405), org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:301), Repository.UserRepo.getUsers(UserRepo.java:55), cleaner.Cleaner.start(Cleaner.java:35), com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863), com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326), com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295), java.security.AccessController.doPrivileged(Native Method), com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294), com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95), com.sun.glass.ui.win.WinApplication._runLoop(Native Method), com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191), java.lang.Thread.run(Thread.java:745)]
When I run get method with postman the backend works, so that tells me it something with client.
client:
glassfish 4.1
Jersey 2.5.1 (JAX-RS RI)
javax.ws.rs-api-2.0.1
server:
glassfish 4.1
jersey 2.26-b03
Thanks in advance!
Add the following dependency to your client to provide a MessageBodyReader implementation that knows how to deserialize an incoming JSON string to an instance of Users.
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.4.4</version>
</dependency>

Getting JAX-RS service to create an object with a JsonObject property

I'd like to get JAXRS to push all json details for a specific class property into a JsonObject object.
Let's say I have the following class:
public class MyMessage implements Serializable {
private PayloadType payloadType;
private JsonObject payload;
}
REST method of:
#POST
#Path("/send")
#Consumes(MediaType.APPLICATION_JSON)
public Response send(MyMessage message)
I'd like to POST the following JSON, but have the payload property set as a javax.json.JsonObject object.
{
payloadType:'MESSAGE',
payload:{
subject:"My Subject",
body:"This is a message"
}
}
I'm running on Glassfish, so I was expecting that message reader for JsonObject were included with org.glassfish.jersey.media, which is support to be included in the GF4.1. Add the following maven dependency just causes ambiguous class exceptions.
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-processing</artifactId>
<version>2.22.1</version>
</dependency>
So there are a couple things stopping you here.
javax.json (or JSONP) does not handle POJOs. It only handles the javax.json API. If you what you are expecting is that the original provider handle the POJO, while the JSONP provider handle the javax.json, it doesn't work like that. Either you will use the one that handles the POJOs (which doesn't know javax.json or you use the one that handles javax.json. (We do make this happen below though :-)
Glassfish's default provider is MOXy. So we need to disable to to use any other provider. To disable MOXy, you need to set this property
ServerProperties.MOXY_JSON_FEATURE_DISABLE
to true. Either in your web.xml or your Java config.
So to make this work, we should make sure that we are using Jackson. Jackson has the jackson-datatype-jsr353 module which allows to do exactly what you are trying to do, javax.json in POJO.
Glassfish has the Jackson provider already, but you should add it anyway in a provided scope. So add these two dependencies
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.10.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr353</artifactId>
<version>2.3.3</version>
</dependency>
If yoo pay attention to the versions, I am using the same versions that are included in Glassfish 4.1. It uses Jersey 2.10.4 and Jackson 2.3.3. You want the versions to conflict. Even though the jersey-media-json-jackson is provided, it's still a good idea to try and use the same version as the server, when compiling.
Also you should register the JacksonFeature with your application.
And the last thing we need is to register the JSR353Module so that we can get the javax.json support with Jackson. To do that just register the following provider with your application.
#Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {
private final ObjectMapper mapper;
public ObjectMapperProvider() {
mapper = new ObjectMapper();
mapper.registerModule(new JSR353Module());
}
#Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
That's it. I've tested it, and it should work.

JAXBException occurred : unexpected element while calling Rest Service from Postman client

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

Restful WebService call with Jersey client version 2.2

CASE
I am trying to fetch User data to Servlet filter using REST service.
POM.xml
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
CODE
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Client client = ClientBuilder.newClient(new ClientConfig());
String entity = client.target("http://localhost:8080/insame/webresources/com.insame.entity.users")
.path("count")
.request(MediaType.TEXT_PLAIN)
.get(String.class);
System.out.println("entity-------->" +entity);
REST:
#GET
#Path("count")
#Produces("text/plain")
public String countREST() {
return String.valueOf(super.count());
}
PROBLEM
javax.ws.rs.ProcessingException: java.net.SocketException: Unexpected end of file from server
at org.glassfish.jersey.client.HttpUrlConnector.apply(HttpUrlConnector.java:202)
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:215)
at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:650)
WARNING: StandardWrapperValve[com.insame.service.ApplicationConfig]: Servlet.service() for servlet com.insame.service.ApplicationConfig threw exception
javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:904)
at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:749)
at org.glassfish.jersey.client.JerseyInvocation.access$500(JerseyInvocation.java:88)
at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:650)
QUESTION
0) What is wrong in my code?
1) What is the wisest way to fetch data from servlet filter using
REST + JPA?
2) If there is another way to do this, better I mean,
pls let me know?
3) Is the Jersey Client the only way
4) How can I
get EntityManager and call the rest service straight from filter
without Jersey Client?
Jersey documentation and examples:
http://jersey.java.net/documentation/latest/user-guide.html#d0e2481
Thanks,
Sami
0) 500 error code means there is some thing wrong on Server side. May be the action action threw some error even though REST got processed.
1) for simple REST, I have used Restlet and HttpClient. Even jerseyClient with JAXB to process response as POJOs. In my experience, simple HTTP is the best and simplest way to process REST response. You can easily write a wrapper on http code (java.net) to process request/response, create Dom around that
2) and 3) are answered above

Categories