How to configure jackson in spring dispatcher servlet? - json

I want to send json data to controller in spring.How to configure jackson in dispatcher servlet and which jackson files to add in build path/lib?

You need to add the Jackson dependency first:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.7.1</version> //your version//
</dependency>
You must add #ResponseBody statement in your code as well. For example:
public class JSONController {
#RequestMapping(value="{name}", method = RequestMethod.GET)
public #ResponseBody Shop getShopInJSON(#PathVariable String name) {
Shop shop = new Shop();
shop.setName(name);
shop.setStaffName(new String[]{"mkyong1", "mkyong2"});
return shop;
}
}
Also, add < mvc:annotation-driven /> into your Spring XML configuration file.
You can find a full example of Jackson and Spring in this link.

Related

Validating Post Json Data Spring Boot

Controller
#RequestMapping(value="/create", method=RequestMethod.POST, consumes={"application/json"})
public Alien addDetails(#RequestBody Alien alien){
return repo.save(alien);
}
Alien.java
#Entity
public class Alien{
#Id
private int id;
private String name;
private String planet;
Getter and setter
Now I want to validate the post json data before saving it to the database.
If any of the field is empty then the controller should return an error.
For example
{"id": 1, "name": "Alien1", "planet":"Mars" }
This is acceptable json data
But if there is any field is missing such as
{"name": "Alien1", "planet":"Mars" }
Then the controller should return an error and not creating the instance of Alien
I tried with #Valid #NotNull still the controller creates an empty instance of Alien and save to the database.
First of all, you should add spring boot validation dependency into your pom.xml :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
And then add annotations like #NotBlank or #NotEmpty to verify if a value is assigned to that field or not. Those annotations should be on the top of your entity's attributes which you want to validate them.For example:
public class Alien{
#NotBlank(message="Name is mandatory")
private String name;
}
Finally, add #Valid annotation into your controller method like:
public Alien addDetails(#Valid #RequestBody Alien alien){
return repo.save(alien);
}
You should add #Validated annotation to your controller to make #Valid annotation do the work. You should also annotate fields in your Entity with constraints.
I.e., name could be #NotBlank.
And yes, make sure that you have imported:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Edit:
In Controller, you should not accept Entity as a body. Instead, you should create a DTO object and then map it to the Entity in the service. You should also put validation constraints on the DTO!

Jackson Object Mapper class given an error Spring mvc

Jackson Object Mapper class given an error Spring mvc
All required jar already added no error in project like jackson-core-asl, jackson-core-2.2.3 and jackson-all 1.9.0 still getting error
Remove the unnecessary jackson-all and jackson-core-asl dependencies.
Include the only one jackson-databind that automatically de/serializes the objects.
<jackson.version>2.8.9</jackson.version>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
Don't forget to return the whole List<Demo> instead of String.
#RequestMapping(value="/getJson", method = RequestMethod.GET)
public List<Demo> listJsonList {
// ...
return alldatalist;
}
And please, next time copy-paste the source code as a text, not as the image :)

How to receive JSON Messages in POST body in a JAX-RS Restful web service in CXF?

I'm trying to develop a REST service using Apache-CXF, on top of JAX-RS. For starters, I have a method called test that receives a String message and int value. I want the clients to be able to pass these parameters in a POST message body. I can't seem to achieve this.
Before I paste the code here, here are some details:
I'm using CXF without Spring
It's not a web app, so I don't have the WEB-INF folder with the web.xml
I test the service using SoapUI and Postman (Google Chrome application)
With the following code, I get WARNING: javax.ws.rs.BadRequestException: HTTP 400 Bad Request:
DemoService.java
#WebService(targetNamespace = "http://demoservice.com")
#Path("/demoService")
public interface DemoService {
#POST
#Path("/test")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public String test (String message, int value);
}
DemoServiceImpl.java
public class DemoServiceImpl implements DemoService {
#Override
public String test(String message, int value) {
return "test message: " + message + " value = : " + value;
}
}
DemoServer.java
public class DemoServer{
public static void main(String[] args) {
JAXRSServerFactoryBean serverFactory = new JAXRSServerFactoryBean();
DemoService demoService = new DemoServiceImpl();
serverFactory.setServiceBean(demoService);
serverFactory.setAddress("http://localhost:9090");
serverFactory.create();
}
}
My POM.xml (minus the attributes in the root tag, everything's there)
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>demo</groupId>
<artifactId>demoService</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<cxf.version>3.0.0</cxf.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
<!-- Jetty is needed if you're are not using the CXFServlet -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-service-description</artifactId>
<version>3.0.0-milestone1</version>
</dependency>
</dependencies>
</project>
Testing with {"message":"hello there!", "value":"50"} to the URL http://localhost:9090/demoService/test gave a HTTP 400 Bad Reuest.
Then I saw this question on S.O.: How to access parameters in a RESTful POST method and tried this:
added the following nested class in DemoServer.java:
#XmlRootElement
public static class TestRequest {
private String message;
private int value;
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public int getValue() { return value; }
public void setValue(int value) { this.value = value; }
}
I also modified the DemoService interface and the implementation to use this class as a parameter in the test method, although this is still ultimately not what I want to do. (just showing the implementation here, question's already getting long):
#Override
public String test(TestRequest testRequest) {
String message = testRequest.getMessage();
int value = testRequest.getValue();
return "test message: " + message + " value = : " + value;
}
And to fix this error that I got: SEVERE: No message body reader has been found for class DemoService$TestRequest, ContentType: application/json (in Postman I see error 415 - unsupported media type) I added the following dependencies (jettison and another thing) to the POM.xml:
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.3.5</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-extension-providers</artifactId>
<version>2.6.0</version>
</dependency>
I tested the service using the following JSON message, in a HTTP POST request:
{"testRequest":{"message":"hello there!", "value":"50"}}
This works. Though this solution where I use a TestRequest class to encapsulate the parameters works, that's not the solution I'm looking for. I want to be able to pass the two parameters in a JSON message, without having to introduce this TestRequest class (explicitly).
Questions:
Would this be easier to implement using Jersey?
I don't have a web.xml nor a WEB-INF folder, so I can't configure CXF in a cxf.xml file can I? A lot of tutorials online seem ot use a lot of XML configuration, but I don't want to deploy a framework like TomEE or Spring or Glassfish just to do that.
Searching online for solutions, I came across Spring Boot. Would you recommend using that, perhaps? Would that make developing web services like this easier?
Also, how do I get it to return the value in JSON format (or is it not supposed to do that for Strings?)
My friend pointed me to this stack exchange question: JAX-RS Post multiple objects
and also the following documentation: http://cxf.apache.org/docs/jax-rs-and-jax-ws.html
which states:
public class CustomerService {
public void doIt(String a, String b) {...};
}
By default JAX-RS may not be able to handle such methods as it
requires that only a single parameter can be available in a signature
that is not annotated by one of the JAX-RS annotations like
#PathParam. So if a 'String a' parameter can be mapped to a #Path
template variable or one of the query segments then this signature
won't need to be changed :
#Path("/customers/{a}")
public class CustomerService {
public void doIt(#PathParam("a") String a, String b) {...};
}
So, to answer my question, NO, it cannot be done.

Java EE7 REST server no longer returning List<String> as JSON

The following example works in a Java EE6 (Glassfish3) project of mine but failed after I switched to Java EE7 (Glassfish4). The HTTP request returns "500 Internal Error" without any message in the Glassfish server log. The project was setup using NetBeans8 as Maven Web Project and has no special dependencies, beans.xml or other configuration.
#RequestScoped
#Path("generic")
public class GenericResource {
#GET
#Path("ping")
#Produces(APPLICATION_JSON)
public List<String> debugPing() {
return Arrays.asList("pong");
}
And then:
$ curl -v http://localhost:8080/mavenproject2/webresources/generic/ping
> GET /mavenproject2/webresources/generic/ping HTTP/1.1
...
< HTTP/1.1 500 Internal Server Error
As as I understand, all REST handling is done by the Jackson reference implementation and that Jackson uses Jersey as underlaying JSON library. One of the two is supposed to have some kind of provider for all basic data types. Only custom made classes need a self written ObjectMapper. Are these concepts still correct?
It took me some hours but I finally solved this question myself.
First fact is that the Glassfish4 JAX-RS implementation "Jersey" as switched its underlying JSON library from Jackson 1.x to Eclipselink MOXy. The latter seems not be able to convert Lists, Arrays and arbitrary POJOs to JSON out of the box. Therefore I tried to force JAX-RS to use Jackson 2.x and disable MOXy.
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
// This is Jackson 2.x, Jackson 1.x used org.codehaus.jackson!
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#ApplicationPath("rest")
public class RestConfig extends Application {
private final static Logger log = LoggerFactory.getLogger(RestConfig.class);
#Override
public Set<Object> getSingletons() {
Set<Object> set = new HashSet<>();
log.info("Enabling custom Jackson JSON provider");
set.add(new JacksonJsonProvider() /* optionally add .configure(SerializationFeature.INDENT_OUTPUT, true) */);
return set;
}
#Override
public Map<String, Object> getProperties() {
Map<String, Object> map = new HashMap<>();
log.info("Disabling MOXy JSON provider");
map.put("jersey.config.disableMoxyJson.server", true);
return map;
}
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
// ... add your own REST enabled classes here ...
return resources;
}
}
My pom.xml contains:
<dependency>
<!-- REST (Jackson as JSON mapper) -->
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<!-- REST (Jackson LowerCaseWithUnderscoresStrategy etc.) -->
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
</dependency>
Hope this helps someone!

Consume a RESTful WS using Spring MVC and Jackson

I would like to consume a RESTful WS using Spring and Jackson.
I'm considering a JSON stream fetched by using Facebook Graph (FC Juventus's JSON data-stream)
This is my controller:
#Controller
public class ConsumeWSController {
#RequestMapping(value = "/consumews", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Consume a RESTful webservice.", locale);
RestTemplate restTemplate = new RestTemplate();
Page page = restTemplate.getForObject("http://graph.facebook.com/juventus", Page.class);
model.addAttribute("pageAbout", page.getAbout());
model.addAttribute("pageAwards", page.getAwards());
return "consumews";
}
}
And the Page class:
#JsonIgnoreProperties(ignoreUnknown = true)
public class Page {
private String about;
private String awards;
public String getAbout() {
return about;
}
public void setAbout(String about) {
this.about = about;
}
public String getAwards() {
return awards;
}
public void setAwards(String awards) {
this.awards = awards;
}
}
But the console returns this error:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [my.proj.Page] and content type [application/json;charset=UTF-8]
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
How can I fix this error?
Make sure that you have added the correct Jackson package to your classpath. For Jackson 2 and you use Maven:
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.3.1</version>
</dependency>
Or if you use the old Jackson add:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.13</version>
</dependency>
You need to define Jackson as your default message converter for JSON content. This is what I do (I use GSON so this might not be the exact syntax for the Jackson message converter):
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
</list>
</property>
</bean>
But since you're not defining your RestTemplate as a Spring-managed bean, you need to do it manually:
restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
PS. I see you're using the newer Jackson dependency so the proper mapper might be different in that case.