RESTful service doesn't map json into object properly - json

I have restful service with resource which consumes json, but when i send test request i got empty values in my model object.
Here is service:
#Path("bot")
public class BotResource {
private final Logger log = LogManager.getLogger(BotResource.class);
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response update(Json update){
log.info("test");
return Response
.ok()
.build();
}
}
Here is model object
import com.fasterxml.jackson.annotation.JsonProperty;
public class Json {
#JsonProperty("update_id")
private String Id;
public Json() {
}
public String getId() {
return Id;
}
public void setId(String Id) {
this.Id = Id;
}
}
so when i send post request with body {"update_id": 37197384} i have null attribute Id. Glassfish 5 causes no errors about this.

Related

how to add custom objectMapper for a specific spring rest controller

I have two controllers in my micro service both are POST and accepts Request body as JSON, one is working fine and another one's JSON input from some othet team and it is with root class name , so I need to write custom object mapper for this later controller, could you please guys help,
please find the codes below,
#RestController
#Slf4j
public class Controller2 {
#RequestMapping(value = "/some/update", method = RequestMethod.POST)
public String updateEmd(#RequestBody final UpdateEMDRequest updateEMDRequest) throws JsonProcessingException {
updateEMDRequest.getBookingReference()); // null now
return "success";
}
}
and the sample json is as follows,
{
"UpdateEMDRequest":{
"TransactionStatus":"SUCCESS",
"UniqueTransactionReference":"046060420",
"PreAuthReference":"040520420",
"BookingReference":"8PJ",
"CarrierCode":"AS",
"TransactionMode":"Batch",
"CallBackUrl":"www.test.com/op/update",
"Offers":[
{
"Offer":{
"traveler":{
"firstName":"AHONY",
"surname":"DNEN",
"EMD":[
"081820470"
]
}
}
}
]
}
}
UpdateEMDRequest,java
#JsonInclude(Include.NON_NULL)
public class UpdateEMDRequest {
#JsonProperty("UniqueTransactionReference")
private String uniqueTransactionReference;
#JsonProperty("TransactionStatus")
private String transactionStatus;
#JsonProperty("PreAuthReference")
private String preAuthReference;
#JsonProperty("BookingReference")
private String bookingReference;
#JsonProperty("CarrierCode")
private String carrierCode;
#JsonProperty("TransactionMode")
private String transactionMode;
#JsonProperty("CallBackUrl")
private String callBackUrl;
#JsonProperty("Offers")
private List<Offers> offers;
}
So this json is not parsed properly and updateEMDRequest's properties are null always.

Unable to get through CXF with JSON

I am trying to build a CXF RESTFul service with JSON as input and output. I am using JAXRSServerFactoryBean to boot my service. When I try to hit the URL from a client program, I am getting the following exception. My program is very simple and attached the same at the bottom.
Please help.
May 19, 2015 11:03:30 PM org.apache.cxf.jaxrs.provider.AbstractJAXBProvider handleExceptionStart
WARNING: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[0,0]
Message: A JSONObject text must begin with '{' at character 0 of
at org.codehaus.jettison.mapped.MappedXMLInputFactory.createXMLStreamReader(MappedXMLInputFactory.java:51)
at org.codehaus.jettison.AbstractXMLInputFactory.createXMLStreamReader(AbstractXMLInputFactory.java:116)
at org.apache.cxf.jaxrs.provider.json.utils.JSONUtils.createStreamReader(JSONUtils.java:162)
at org.apache.cxf.jaxrs.provider.json.JSONProvider.createReader(JSONProvider.java:290)
at org.apache.cxf.jaxrs.provider.json.JSONProvider.createReader(JSONProvider.java:280)
at org.apache.cxf.jaxrs.provider.json.JSONProvider.readFrom(JSONProvider.java:233)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(JAXRSUtils.java:1337)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java:1288)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:824)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:787)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:212)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:77)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
May 19, 2015 11:03:30 PM org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper toResponse
WARNING: javax.ws.rs.BadRequestException: HTTP 400 Bad Request
at org.apache.cxf.jaxrs.utils.SpecExceptions.toBadRequestException(SpecExceptions.java:84)
at org.apache.cxf.jaxrs.utils.ExceptionUtils.toBadRequestException(ExceptionUtils.java:114)
at org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.handleExceptionEnd(AbstractJAXBProvider.java:705)
at org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.handleXMLStreamException(AbstractJAXBProvider.java:734)
at org.apache.cxf.jaxrs.provider.json.JSONProvider.readFrom(JSONProvider.java:261)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(JAXRSUtils.java:1337)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java:1288)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:824)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:787)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:212)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:77)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:251)
at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:234)
at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:70)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1129)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1065)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[0,0]
Message: A JSONObject text must begin with '{' at character 0 of
at org.codehaus.jettison.mapped.MappedXMLInputFactory.createXMLStreamReader(MappedXMLInputFactory.java:51)
at org.codehaus.jettison.AbstractXMLInputFactory.createXMLStreamReader(AbstractXMLInputFactory.java:116)
at org.apache.cxf.jaxrs.provider.json.utils.JSONUtils.createStreamReader(JSONUtils.java:162)
at org.apache.cxf.jaxrs.provider.json.JSONProvider.createReader(JSONProvider.java:290)
RestFulServiceStarter
public class RestFulServiceStarter {
public static void main(String[] args) {
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(ProfileService.class);
sf.setResourceProvider(ProfileService.class,
new SingletonResourceProvider(new ProfileServiceImpl()));
sf.setAddress("http://localhost:9999/");
Server server = sf.create();
}
}
ProfileService
#Path("/profile/")
public interface ProfileService {
#GET
#Path("/static/")
#Consumes({ MediaType.APPLICATION_JSON })
#Produces({ MediaType.APPLICATION_JSON })
public Response getStaticProfiles(ProfileRequest pr);
}
ProfileServiceImpl
public class ProfileServiceImpl implements ProfileService {
public Response getStaticProfiles(ProfileRequest pr) {
return Response.status(200).entity(pr).build();
}
}
ProfileRequest
#XmlRootElement ( name = "profile" )
public class ProfileRequest {
private String name="";
private String country="";
private String region="";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
}
Your interface method is annotated with a #GET method, yet it also has an entity parameter (ProfileRequest). Try #POST.

RESTful service with postman

I'm working on a jax-rs RESTful application and I have a service that is supposed to save a JSON objet into a database through JPA. The service class is something like:
#Path("/items")
#Stateless
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class ItemsService {
#Inject
protected IItemsLogic itemsServiceLogic;
#POST
public ItemDTO create(ItemDTO item){
return itemsServiceLogic.createItem(item);
}
}
the itemsServiceLogic is just a class that transforms the DTO into another Java class declared as an entity in order to be serialized in a database through JPA.
What happens is that I'm testing the application through the google chrome browser client Postman but when I send a JSON objet into the POST method, the received DTO has no properties so the database doesn't save anything, as all the DTO's properties are null.
I'm using Glassfish 4.0 to host my application and everything with the database works fine. What could be wrong?
The DTO class would be:
#XmlRootElement
public class ItemDTO {
//Id private
Long id;
//item's description
private String description;
//item's name
private String name;
//Setters and getters
public Long getId(){
return id;
}
public String getDescription(){
return description;
}
public String getName(){
return name;
}
public void setId(Long nId){
this.id=nId;
}
public void setDescription(String nDescription){
this.description = nDescription;
}
public void setName(String nName){
this.name=nName;
}
}
And i'm sending the JSON:
{"id":1,"description":"some item","name":"item1"}

How to produce error response in json

Am writing a Restful Webservice Impl, where i consume and produce response in JSON format by annotating #Produces("application/json"). Am producing JSON response as well. Here am handling exception with a class where it has error code and error message. When am getting exception it is not produced in application/json format. I used ExceptionMapper to find a solution but it is `text/plain format.
snippet
public Class Confiuration{
#Path("getData")
#Consumes("application/json")
#Produces("application/json")
public JSONGetDataResponseVo getData(GetDataRequestVo datarequestVO)
throws FaultResponse {
JSONGetDataResponseVo response=new JSONGetDataResponseVo ();
DataServiceValidator.validateGetConfigurationAndDataRequest(datarequestVO);
....
....
}catch(ApplicationException applicationException){
throw new FaultResponse(applicationException,locale);
}
}
FaultResponseMapper
#Provider
public class FaultResponseMapper implements ExceptionMapper<FaultResponse> {
#Context
private HttpHeaders headers;
public Response toResponse(FaultResponse faultResponse) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(faultResponse).type(MediaType.APPLICATION_JSON).build();
}
}
Application Exception
public abstract class ApplicationException extends Exception{
private java.lang.String errorCode;
public ApplicationException(String errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public ApplicationException(String message) {
super(message);
}
public java.lang.String getErrorCode() {
return this.errorCode;
}
public abstract String getLocaleMessage(Locale locale);
}
FaultResponse
public class FaultResponse extends WebApplicationException {
private String errorCode;
private String errorMessage;
private String localErrorMessage;
public FaultResponse(String errorCode, String errorMessage,
String localErrorMessage) {
this.errorCode = errorCode;
this.errorMessage = errorMessage;
this.localErrorMessage = localErrorMessage;
}
public FaultResponse(ApplicationException applicationException,
Locale locale) {
this.errorCode = applicationException.getErrorCode();
this.errorMessage = applicationException.getMessage();
if (locale != null
&& applicationException.getLocaleMessage(locale) != null) {
this.localErrorMessage = applicationException
.getLocaleMessage(locale);
} else {
this.localErrorMessage = applicationException.getMessage();
}
}
}
So here how can i produce my faultResponse in JSON format.
This has to do with the fact that you are returning an exception as a response. I would
Make an exception mapper for ApplicationException.
Refactor FaultResponse to not extend and exception. Just create it in the mapper.
In order to see the response, you will need to send a status other than No Content. You can't have a body in it. Send somethng like Bad Request.
You can just declare the resource method as throws ApplicationException. You don't need to catch it and rethrow.
I've made these changes, and it works fine.
UPDATE: with complete test
Added getters (required for marshalling) to FaultResponse and remove the exception extension
public class FaultResponse {
...
public String getErrorCode() { return errorCode; }
public String getErrorMessage() { return errorMessage; }
public String getLocalErrorMessage() { return localErrorMessage; }
...
}
Created a Service for testing and ApplicationException implementation
public class ApplicationExceptionImpl extends ApplicationException {
public ApplicationExceptionImpl(){
this("400", "Bad Request");
}
public ApplicationExceptionImpl(String errorCode, String message) {
super(errorCode, message);
}
#Override
public String getLocaleMessage(Locale locale) {
return "Bad Request";
}
}
public class FaultService {
public void doSomething() throws ApplicationException {
throw new ApplicationExceptionImpl();
}
}
Resource class
#Path("fault")
public class FaultResource {
FaultService service = new FaultService();
#GET
public Response getException() throws ApplicationException {
service.doSomething();
return Response.ok("Cool").build();
}
}
ExceptionMapper
#Provider
public class ApplicationExceptionMapper implements ExceptionMapper<ApplicationException> {
#Override
public Response toResponse(ApplicationException exception) {
FaultResponse response = new FaultResponse(exception, Locale.ENGLISH);
return Response.status(Response.Status.BAD_REQUEST)
.entity(response).type(MediaType.APPLICATION_JSON).build();
}
}
ApplicationException class is left the same
curl -v http://localhost:8080/api/fault
{"errorCode":"400","errorMessage":"Bad Request","localErrorMessage":"Bad Request"}
If after this you are still not seeing JSON, it's possible you do not have a provider configured. If this is the case, please show your application configuration, along with your project dependencies.

Jersey - Serializing a POJO with json - nested objects will be ignored

HiAll,
i have the following problem in development branch:
If i use the jersey REST service to serialize the POJO containig a list of the nested other POJO, then this nested POJO will be NOT serialized. This problem is reproducible only in branch.
If i prototype using POJO structur liked in branch, i have no problem.
The Details:
The POJO (Domain):
public class Article {
private int id;
private int name;
// getter & setter
}
The POJO ( DTO)
public class DTO {
private List<Article> articles;
private String message;
public DTO {
articles= new ArrayList<>();
}
getArticles() {
return articles;
}
getArticlesCount() {
return articles.size();
}
public void getMessage() {
return message;
}
public String getMessage() {
return message;
}
....
}
It will be created the 1 article with id = 1 and name "firstArticle" the
The results of serialization after service call to find all articles:
in branch
*{"message":"1 article found","articlesCount":1
}*
in prototype
{
{"message":"1 article found","articlesCount":1[{"id":1,"name":"firstArticle"]}
}
i have no idia what's happened. I checked out all settings (web.xml, jersey version, etc.)
If you use Jackson JSON library, your POJO will be automatically handled by Jackson JSON lib to convert between JSON and POJO. You also need to add the following lines in your web.xml:
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
Then in your Jersey resource class, use #Produces and #Consumes annotation to indicate the data format is JSON:
#Path("/myResource")
#Produces("application/json")
public class SomeResource {
#GET
public String doGetAsJson() {
...
}
}
Follow the above answer to set up Jersey POJO mappping, and then try the following nested POJO example.
Article class:
public class Article {
private int id;
private String name;
public Article(int id, String name) {
this.id = id;
this.name = name;
}
//getter and setter ...
}
The Book class that contains the Article class:
public class Book {
private List<Article> articles;
private String message;
private int articleCount;
public List<Article> getArticles() {
return articles;
}
public void setArticles(List<Article> articles) {
this.articles = articles;
setArticleCount(articles.size());
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getArticleCount() {
return articleCount;
}
public void setArticleCount(int articleCount) {
this.articleCount = articleCount;
}
}
Finally in the Jersey resource class NestedPojoResource:
#Path("/nested-pojo")
public class NestedPojoResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
public Book getNestedPojo() {
Book book = new Book();
List<Article> articles = new ArrayList<Article>();
articles.add(new Article(1, "firstArticle"));
articles.add(new Article(2, "secondArticle"));
book.setArticles(articles);
book.setMessage(book.getArticleCount() + " articles found");
return book;
}
}
When you go to http://example.com/myappname/nested-pojo, you will see the correct JSON output which contains the nested POJO fields:
{"articles":[{"id":1,"name":"firstArticle"},{"id":2,"name":"secondArticle"}],"message":"2 articles found","articleCount":2}