I have this Model class:
package org.myapp.model;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="Message")
#XmlAccessorType(XmlAccessType.FIELD)
public class Message {
public long id;
public String message;
public Date created;
public String author;
public Message() {
}
public Message(long id,String message, String author) {
this.id = id;
this.message = message;
this.author = author;
this.created = new Date();
}
#XmlElement
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
#XmlElement
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
#XmlElement
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
The Service Class:
package org.myapp.services;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.myapp.model.Message;
public class MessageService {
public List<Message> getAllMessages(){
Message msg1 = new Message(1L,"How are you?", "natalie");
Message msg2 = new Message(2L,"How are you?", "amir");
List<Message> msglist = new ArrayList<Message>();
msglist.add(msg1);
msglist.add(msg2);
return msglist;
}
}
The Resource Class:
package org.myapp.resource;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.myapp.model.Message;
import org.myapp.services.MessageService;
#Path("messageresource")
public class MessageResource {
MessageService messageService = new MessageService();
#GET
#Produces(MediaType.APPLICATION_XML)
public List<Message> getMessage() {
return messageService.getAllMessages(); //"app chal rhi hai!";
}
#GET
#Produces(MediaType.APPLICATION_XML)
#Path("/{messageId}")
public String getMessageID(#PathParam("messageId") String messageId) {
Message message = new Message(1L,"How are you?", "natalie");
return message.getMessage()+", "+messageId;
}
}
I am trying to print the data in Service(MessageService) class in an XML format. I think, the error is being caused because the return value of this class' method (return type List<Message>) and the tag #XMLRootElement on the top of the Model (Message) class are not consistent. I tried different MediaType properties but nothing helped.
When I am accessing this path : localhost:8080/messengerapp/webapi/messageresource
I am getting this error - Internal Server Error
I have just started to learn to write web services.I have tried different ways to get around this problem but nothing is helping me. Please help me understand and solve this.
try with this,
annotate the root element of xml
#XmlRootElement (name="Messages")
public class MessageService implements Serializable{
private List<Message> msglist = new ArrayList<Message>();
public List<Message> getAllMessages(){
Message msg1 = new Message(1L,"How are you?", "natalie");
Message msg2 = new Message(2L,"How are you?", "amir");
msglist.add(msg1);
msglist.add(msg2);
return msglist;
}
public void setAllMessages(List<Message> msglist){
this.msglist = msglist;
}
}
structure of the xml
<Messages> <!-- root element of xml -->
<Message>
...
</Message>
<Message>
...
</Message>
</Messages>
Related
I have following model class:
package com.restAPIExmaple;
public class ApiModel {
private String City;
private String TeamName;
private String QBName;
public ApiModel() {
}
public ApiModel(String city, String teamName, String qBName) {
City = city;
TeamName = teamName;
QBName = qBName;
}
public String getCity() {
return City;
}
public void setCity(String city) {
City = city;
}
public String getTeamName() {
return TeamName;
}
public void setTeamName(String teamName) {
TeamName = teamName;
}
public String getQBName() {
return QBName;
}
public void setQBName(String qBName) {
QBName = qBName;
}
}
Here is the service class:
package com.restAPIExmaple;
import java.util.List;
import org.springframework.stereotype.Service;
import java.util.Arrays;
#Service
public class ApiService {
private List <ApiModel> score = Arrays.asList(
new ApiModel("Jacksonville","Jaguars","Gardner Minshew"),
new ApiModel("Tempa Bay", "Buccaneer", "Tom Brady"),
new ApiModel("San Fran", "49rs", "Jimmy Garoppolo"),
);
public List<ApiModel> getScores()
{
return score;
}
public ApiModel getTeam(String team){
return score.stream().filter(t -> t.getTeamName().equalsIgnoreCase(team)).findFirst().get();
}
}
The Controller is as below:
package com.restAPIExmaple;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
#RestController
#RequestMapping("/football")
public class ApiController {
#Autowired
private ApiService apiService;
#GetMapping(value = "/scores", produces = {MediaType.APPLICATION_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE})
public List<ApiModel> getScores(){
return apiService.getScores();
}
#GetMapping(value="/{team}", produces = {MediaType.APPLICATION_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE})
public ApiModel getTeam(#PathVariable String team){
return apiService.getTeam(team);
}
}
Here is the response in xml:
<List>
<item>
<teamName>Jaguars</teamName>
<city>Jacksonville</city>
<qbname>Gardner Minshew</qbname>
</item>
<item>
<teamName>Buccaneer</teamName>
<city>Tempa Bay</city>
<qbname>Tom Brady</qbname>
</item>
<item>
<teamName>49rs</teamName>
<city>San Fran</city>
<qbname>Jimmy Garoppolo</qbname>
</item>
</List>
Problem: The order of the object properties has been changed in the out put. I cant get City, Team name , QBname in that order order in the response. When I generate getter and setter using Eclipse, the order of the fields there is different from the model class as well. Any idea? Thank you.
start variable name with simple letters. that's the case
The springboot application exposes the graphql API on the endpoint "localhost:8091/rest/books". When I test it with Postman passing the query in the body as graphQL type it gives error "Invalid Syntax", whereas when I pass the same query as raw text, it yields correct results. I'm using HSQL. The structure of my application is:
The files with their code respectively are:
Book.java
package com.techprimers.graphql.springbootgrapqlexample.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
//#AllArgsConstructor
//#NoArgsConstructor
#Setter
#Getter
#Table
#Entity
public class Book {
#Id
private String isn;
public Book() {
super();
}
public Book(String isn, String title, String publisher, String[] authors, String publishedDate) {
super();
this.isn = isn;
this.title = title;
this.publisher = publisher;
this.authors = authors;
this.publishedDate = publishedDate;
}
public String getIsn() {
return isn;
}
public void setIsn(String isn) {
this.isn = isn;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
public String[] getAuthors() {
return authors;
}
public void setAuthors(String[] authors) {
this.authors = authors;
}
public String getPublishedDate() {
return publishedDate;
}
public void setPublishedDate(String publishedDate) {
this.publishedDate = publishedDate;
}
private String title;
private String publisher;
private String[] authors;
private String publishedDate;
}
BookRepository.java
package com.techprimers.graphql.springbootgrapqlexample.repository;
import com.techprimers.graphql.springbootgrapqlexample.model.Book;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BookRepository extends JpaRepository<Book, String> {
}
BookResource.java
package com.techprimers.graphql.springbootgrapqlexample.resource;
import com.techprimers.graphql.springbootgrapqlexample.service.GraphQLService;
import graphql.ExecutionResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#CrossOrigin(origins = "http://localhost:3000")
#RequestMapping("/rest/books")
#RestController
public class BookResource {
#Autowired
GraphQLService graphQLService;
#PostMapping
public ResponseEntity<Object> getAllBooks(#RequestBody String query) {
ExecutionResult execute = graphQLService.getGraphQL().execute(query);
return new ResponseEntity<>(execute, HttpStatus.OK);
}
}
AllBooksDataFetcher.java
package com.techprimers.graphql.springbootgrapqlexample.service.datafetcher;
import com.techprimers.graphql.springbootgrapqlexample.model.Book;
import com.techprimers.graphql.springbootgrapqlexample.repository.BookRepository;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
#Component
public class AllBooksDataFetcher implements DataFetcher<List<Book>>{
#Autowired
BookRepository bookRepository;
#Override
public List<Book> get(DataFetchingEnvironment dataFetchingEnvironment) {
return bookRepository.findAll();
}
}
BookDataFetcher.java
package com.techprimers.graphql.springbootgrapqlexample.service.datafetcher;
import com.techprimers.graphql.springbootgrapqlexample.model.Book;
import com.techprimers.graphql.springbootgrapqlexample.repository.BookRepository;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class BookDataFetcher implements DataFetcher<Book>{
#Autowired
BookRepository bookRepository;
#Override
public Book get(DataFetchingEnvironment dataFetchingEnvironment) {
String isn = dataFetchingEnvironment.getArgument("id");
return bookRepository.findById(isn).get();
}
}
And in the resources folder is
Books.graphql (contains schema)
schema {
query: Query
}
type Query {
allBooks: [Book]
book(id: String): Book
}
type Book {
isn: String
title: String
publisher: String
authors: [String]
publishedDate: String
}
The Java Rest Api prints on http://localhost:8080/books
[{},{},{}]
instead of the booklist object. I use a main method a book_controller and a book model. Firstly I add a couple of books in the list in the method getbooks() and then I return them as a list.
Why does this happen?
application.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
#SpringBootApplication (exclude = SecurityAutoConfiguration.class)
public class Lab6NosApplication {
public static void main(String[] args) {
SpringApplication.run(Lab6NosApplication.class, args);
}
}
Book_controller.java
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import ch.qos.logback.classic.Logger;
import net.minidev.json.JSONArray;
#Controller
public class Book_controller implements ErrorController, Serializable {
#GetMapping("books")
public #ResponseBody List<book> getbooks() {
List<book> bookList = new ArrayList<book>();
bookList.add(new book(1,"lokesh","gupta"));
bookList.add(new book(2,"lokesh","gupta"));
bookList.add(new book(3,"lokesh","gupta"));
java.lang.System.out.print(bookList);
return bookList;
}
#RequestMapping("/error")
#ResponseBody
public String handleError(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
return String.format("<html><body><h2>Error Page</h2><div>Status code: <b>%s</b></div>"
+ "<div>Exception Message: <b>%s</b></div><body></html>",
statusCode, exception==null? "N/A": exception.getMessage());
}
#Override
public String getErrorPath() {
return "/error";
}
}
Book.java
public class Book {
public Book(Integer id, String title, String author) {
super();
this.id = id;
this.title = title;
this.author = author;
}
private Integer id;
private String title;
private String author;
//getters and setters
#Override
public String toString() {
return "Employee [id=" + id + ", title=" + title
+ ", author=" + author + "]";
}
}
Thank you!
You see it empty because your Book class doesn't have public getters or properties, so the serializer won't be able to access it's values.
Add getters to your Book class:
public Integer getId(){
return this.id;
}
public String getTitle(){
return this.title;
}
public String getAuthor(){
return this.author;
}
You can also improve your code, with better naming such as BookController instead of Book_controller. Have a look at java naming conventions.
Finally, take a look at a #RestController. If you use #RestController, you don't need to have #ResponseBody
I am using the Jersey Client of Sun Version 1.19...
When I send a put request with JSON (but every other request type probably as well) it serializes Number-typed variables with quotes, instead of as plain numbers.
Example:
User.java
package de.topazmedia.component.api.rest.client.ressource;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
#XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
public class User {
Long id;
String username;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return id;
}
public void setUsername(Long id) {
this.id = id;
}
}
Test.java
import javax.ws.rs.core.MediaType;
import org.json.JSONObject;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder;
public class Test {
public static void main(String[] args) {
User user = new User();
user.setId(1);
user.setUsername("Test");
ClientResponse response = null;
WebResource webResource = client.resource(http://192.168.23.56:9181/v1/users/" + user.getId());
Builder builder = webResource.header("Accept-Language", "de").type(MediaType.APPLICATION_JSON_TYPE).accept(MediaType.APPLICATION_JSON_TYPE);
response = builder.put(ClientResponse.class, user);
}
}
The "User JSON" I put as entity in the request is now translated to
{"id":"1","username":"Test"}
BUT it should be without the apostrphes at the id like this:
{"id":1,"username":"Test"}
What is wrong?
The solution of the problem ist quite simple.
Just define a POJO-Mapping in the ClientConfig when instantiating the Client Object:
ClientConfig cc = new DefaultClientConfig();
cc.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
client = Client.create(cc);
I am currently working on a REST-API. I am using Jersey for that.
I programmed a couple of interfaces before, and they all worked fine. Now, I'm doing it exactly the same way (in my opinion), but it somehow won't work.
The Problem is that userGet() does not log any error (the error does not occur inside the TRY-CATCH), and it SEEMS like the method is executed successfully. But the client receives only "500 Internal Server Error"-responses.
Do you have any idea how to find out where the error occures? Or do you already know what I've done wrong?
This is my class which should be returned by the API:
package myproject.model;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class UserModel {
#XmlElement(name = "id")
private long id = -1;
#XmlElement(name = "strUsername")
private String username = null;
#XmlTransient
private String encryptedPassword = null;
#XmlElement(name = "Consultant", nillable = true)
private Consultant consultant = null;
public UserModel(long id, String username, String encPw, Consultant co) {
this.id = id;
this.username = username;
this.encryptedPassword = encPw;
this.consultant = co;
}
public static UserModel fromUser(User u) {
return new UserModel(u.getId(), u.getName(), u.getEncryptedPassword(), u.getConsultant());
}
public User toUser() {
return User.fromUserModel(this);
}
public long getId() {
return id;
}
public String getUsername() {
return username;
}
public String getEncryptedPassword() {
return encryptedPassword;
}
public Consultant getConsultant() {
return consultant;
}
public String toString() {
return "id=" + id + ";username=" + username + ";encPw=" + encryptedPassword;
}
}
My REST-API:
package myproject.rest;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.log4j.Logger;
import org.json.JSONObject;
import myproject.User;
import myproject.UserModel;
import myproject.DBUtil;
import myproject.SecurityUtil;
#Path("/app/user")
public class HandlerUser extends RestEndpoint {
private static Logger log = Logger.getLogger(HandlerUser.class);
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response userGet() {
Connection con = null;
try {
con = DBUtil.getDBConnection();
//SecurityUtil.checkRight(request);
log.info("Collect all Users");
List<UserModel> usermodels = new ArrayList<UserModel>();
Iterator<User> it = User.getAll(con).iterator();
while(it.hasNext()) {
usermodels.add(it.next().toUserModel());
}
GenericEntity<List<UserModel>> entity = new GenericEntity<List<UserModel>>(usermodels) {};
return Response.ok().entity(entity).build();
}
catch(Exception e) {
log.error("An error occured: " + e.toString());
return Response.status(401).entity(e.toString()).build();
}
finally {
DBUtil.close(null, null, con);
}
}
}
EDIT: User.toUserModel() converts a User-Object to a UserModel-Object (which works fine)