Tomcat Server quits working when GET and POST added to it - java

for a project I have to make a Java backend using RESTful services, restservices. When I add a certain resource to my project with a get method and a post method, the server gives a 500 error. When i remove the GET and POST methods, it works fine again. Can anyone explain why it won't work?
Resource file:
package nl.hu.v1ipass.testipass.webservices;
#Path("/aanmeldingen")
public class AanmeldingResource {
private JsonObjectBuilder aanmeldingToJson(Aanmelding aanmelding) {
JsonObjectBuilder job = Json.createObjectBuilder();
job.add("lidnummer", aanmelding.getEter().getLidNummer());
job.add("lidnaam", aanmelding.getEter().getName());
job.add("gerechtnaam", aanmelding.getGerecht().getName());
return job;
}
#GET
#RolesAllowed("admin")
#Produces("appplication/json")
public String getAanmeldingen(#FormParam("datum") String datum) {
AanmeldingService service = new AanmeldingService();
JsonArrayBuilder jab = Json.createArrayBuilder();
for (Aanmelding a : service.getAanmeldingDate(datum)){
jab.add(aanmeldingToJson(a));
}
JsonArray array = jab.build();
return array.toString();
}
#POST
#RolesAllowed({"user", "admin"})
public Response addAanmelding(#FormParam("datum") String datum, #FormParam("gerecht") int gerechtId, #FormParam("lidnummer") int lidnummer) throws SQLException {
AanmeldingService service = ServiceProvider.getAanmeldingService();
if(service.getAanmeldingDate(datum) == null) {
Aanmelding returnAanmelding = service.addAanmelding(lidnummer, gerechtId);
String a = aanmeldingToJson(returnAanmelding).build().toString();
return Response.ok(a).build();
} else {
return Response.status(Response.Status.FOUND).build();
}
}
}
UPDATE: with only the POST method, the server works fine. So what goes wrong in my GET method?

Try changing
#Produces("appplication/json")
to
#Produces("application/json")
notice the spelling mistake

Related

Java API / Jersey put method

it's my first API in Java, so please, keep that in mind ;) I've got Controller.class where I'm keeping all my methods right now ( I will clean it later ;) ). As far as GET methods work perfectly I've got problem with PUT method when I want to create new user - it doesn't work. Any help please ? And advices cause - as I said - I'm newbie when it comes to API ;)
So this is my controller.class :
#Path("/api")
public class Controller {
List<Post> mBartoszPosts;
List<Post> mFelipePosts;
List<Post> mShawnPosts;
List<Post> mDavidPosts;
List<Post> mGraziellaPosts;
List<Post> mAllPosts;
List<User> mUsers;
User bartosz;
User felipe;
User shawn;
User david;
User graziella;
#Path("/user/{id}")
#GET
#Produces("application/json")
public Response getUser(#PathParam("id")int id) {
setUpUsers();
System.out.println("Liczba osob : " + mUsers.size());
for(User user : mUsers) {
if(id == user.getId()) {
String result = user.toString();
return Response.status(200).entity(user).build();
}
}
return null;
}
#Path("/post/{post_id}")
#GET
#Produces("application/json")
public Response getPost(#PathParam("post_id")int post_id) {
setUpUsers();
System.out.println("Liczba osob : " + mUsers.size());
for(Post post : mAllPosts) {
if(post_id == post.getId()) {
String result = post.toString();
return Response.status(200).entity(post).build();
}
}
return null;
}
#Path("/posts")
#GET
#Produces("application/json")
public Response getPosts() {
setUpUsers();
String response = new Gson().toJson(mAllPosts );
return Response.status(200).entity(response).build();
}
#PUT
#Path("user/new/{id}/{post}")
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
public Response updateEmployeeById(#PathParam("id") Integer id,#PathParam("post") String userPost)
{
List<Post>userPosts = new ArrayList();
Post post = new Post(99,userPost,"Bartosz");
userPosts.add(post);
User updatedEmployee = new User(id,"Bartek","Szlapa",userPosts);
if(updatedEmployee.getName() == null) {
return Response.status(400).entity("Please provide the employee name !!").build();
}
updatedEmployee.setId(id);
updatedEmployee.setName(updatedEmployee.getName());
System.out.println(updatedEmployee.getName());
return Response.ok().entity(updatedEmployee).build();
}
public int maxValue(int array[]){
int max = Arrays.stream(array).max().getAsInt();
return max;
}
}
As you see the last method is PUT and it doesn't work: Here is my test client :
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Client client = ClientBuilder.newClient( new ClientConfig().register( Controller.class ) );
WebTarget webTarget = client.target("http://localhost:8080/JerseyDemos/rest").path("api").path("user").path("new").path("77");
List<Post>userPosts = new ArrayList();
Post post = new Post(99,"Bartek Szlapa","Testing post ...");
userPosts.add(post);
User emp = new User(99,"Bartek","Szlapa",userPosts);
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_XML);
Response response = invocationBuilder.put(Entity.entity(emp, MediaType.APPLICATION_XML));
User user = response.readEntity(User.class);
System.out.println(response.getStatus());
System.out.println(user);
}
}
And finally my error :
Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/xml, type=class entities.User, genericType=class entities.User.
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:248)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163)
at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1135)
at org.glassfish.jersey.client.ClientRequest.doWriteEntity(ClientRequest.java:516)
at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:498)
at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:384)
at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:282)
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:278)
at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$0(JerseyInvocation.java:753)
at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
at org.glassfish.jersey.internal.Errors.process(Errors.java:229)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:414)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:752)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:445)
at org.glassfish.jersey.client.JerseyInvocation$Builder.put(JerseyInvocation.java:334)
at test.Test.main(Test.java:33)
Thanks in advance for help!
It seems 2 problems in your client code -
For removing this error, you should add jersey-media-jaxb JAR in your classpath. If you are using maven, add below dependency in your pom.xml -
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-jaxb</artifactId>
<version>${jersey.version}</version>
</dependency>
As per your PUT method API specification -
public Response updateEmployeeById(#PathParam("id") Integer id,#PathParam("post") String userPost) {
Your REST service needs only path parameter id and post. No other input is required. However, in your client code, you are sending User class object emp object while calling your API -
Response response = invocationBuilder.put(Entity.entity(emp, MediaType.APPLICATION_XML));
Since you are not receiving this emp object in your API, so this data will get lost. So, either you should update your API for accepting User class object in request or don't sent this object from your client code.

Change URL pattern of rest API

#Path("/ftocservice")
public class RestService {
#Path("{f}")
#GET
#Produces("application/json")
public Response convertFtoCfromInput(#PathParam("f") float f)
throws Exception {
DbCon db = new DbCon();
ArrayList<Student> students = db.getStudentList();
JSONArray jsonArray = new JSONArray(students);
String result = jsonArray.toString();
return Response.status(200).entity(result).build();
}
}
I'm using above source code to generate rest API and user is requesting through the API as follows.
http://localhost:8080/RestExample/RestService/ftocservice/23
I need to change the request URL as follows.
http://localhost:8080/RestExample/RestService/ftocservice?f=23
Please help to change the source code to change request URL as given. Thanks
Change to use #QueryParam instead:
#Path("/ftocservice")
public class RestService {
#GET
#Produces("application/json")
public Response convertFtoCfromInput(#QueryParam("f") float f)
throws Exception {
DbCon db = new DbCon();
ArrayList<Student> students = db.getStudentList();
JSONArray jsonArray = new JSONArray(students);
String result = jsonArray.toString();
return Response.status(200).entity(result).build();
}
}
See this link for more info on parameter types in JAX-RS.
This tutorial by Mkyong.com is also quite nice.
use #QueryParam instead of #PathParam

How to get array from Http Post in a Restful Web Service?

I have a controller for AngularJS Framework. I use a Http Post Request to send an array to a server. How to get this array in a java method?
This is my controller
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
var indici = new Array();
indici.push(1);
indici.push(2);
$http.post("http://localhost:8080/SistemiDistribuiti/rest/Point/Trovati", indici, {
headers: { 'Content-Type': 'application/json' }
}).success(function(receivedData, status) {
$scope.someData = receivedData;
});
And this is my java class but i don't know how to get my array.
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.POST;
import javax.ws.rs.Consumes;
#Path("Point")
public class PointService {
#POST
#Path("Trovati")
#Consumes(MediaType.APPLICATION_JSON)
public void RetrieveData() {
//how print my array?
}
You have to use #GET as below:
#GET
#Path("/blabla")
public Response receiveListOfStrings(#QueryParam("list") final List<String> list){
log.info("receieved list of size="+list.size());
return Response.ok().build();
}
And request:
GET http://example.com/services/echo?list=balbla&list=asdasd&list=BYE
Post doesn't support this. Or you can use #PUT with complex type.
Put example:
#PUT
public Response putExample(MyObject obj) {
log.info("receieved list of size="+obj.getList().size());
return Response.ok().build();
}
In this put example you can see I used a custom MyObject Here's its codes:
public class MyObject{
private List<String> list = new ArrayList<String>();
public List<String> getList(){
return list;
}
public void setList( List<String> list ){
this.list = list;
}
#Override
public String toString(){
return "MyObject [list=" + list + "]";
}
}
As you can see there's a list property in your MyObject class. So you can print anything by calling getList as my example above.
I agree with #lex82, you don't send the payload within your request. See the documentation for $http.post: https://docs.angularjs.org/api/ng/service/$http#post. Be sure to understand what promises are and how they are used within the HTTP support of Angular.
Here is a sample:
var dataToSend = {
// some JSON data
};
$http.post("/some-url", dataToSend, {
headers: { 'Content-Type': 'application/json' }
}).success(function(receivedData, status) {
$scope.someData = receivedData;
});
That said, you say that you don't receive the data on the server. The first to do is to check your raw request. This can be done within Chrome using the Chrome Developer Tools (CRTL + SHIFT + i). This will give you access to a Network tab containing every request. Click on the request corresponding to your AJAX request and check if there is a payload in your request. If so, it's a problem on your server side within your JAXRS application.
Do you some exceptions within your JAXRS application?
Hope it helps you,
Thierry
Apache has an http library that can be used to make various http requests.
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.2</version>
</dependency>
You will also need a library that can be used to transform your json objects into Java object. Google has created a library called gson that I will use in my example.
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
You are also going to have to create a Java object that represents your data. This will be used to map your json object to a java object or "pojo". I'm not sure what your JSON objects look like, but I'm going to use a generic example called Response.
public class Response
{
private List<Example> examples;
private double total;
private String someString;
public QuoteResponse()
{
super();
}
public List<Examples> getExamples() {
return examples;
}
public void setExamples(List<Examples> examples)
{
this.examples = examples;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
public String getSomeString() {
return someString;
}
public void setPrint_type(String someString) {
this.someString = someString;
}
}
Your java object has to have the same number of fields with the same type and same name as your JSON object.
Next, you will have to write a function that calls your angular api. See an example below:
public Response getJsonData()
{
params = new Params();
String url = "https://www.yoururl.com/controller/function_you_want;
Response response = null;
HttpGet httpGet = new HttpGet(url);
try
{
response = httpClient.execute(httpGet);
//check to make sure that everything is ok
if(response.getStatusLine().getStatusCode() == 200)
{
entity = response.getEntity();
jsonResponse = EntityUtils.toString(entity);
JsonNode root = mapper.readTree(jsonResponse).get("result");
response = gson.fromJson(root.toString(),Response.class);
}
}
catch (IOException e)
{
e.printStackTrace();
}
return response;
}
That's about it. Let me know if you have any questions.

create Entity Tag, but it is null

In my Jersey Rest Service i tried to create an entity tag with:
String content = 12sdfs-345dsdfsdf-231yscysd;
String createdContent = create(content);
return Response.created(createdUri).entity(createdContent).build();
like its written in the jersey documentation. But createdContent is null. Whats wrong?
The full code is:
#POST
#Consumes("application/x-www-form-urlencoded")
public Response postObject(#FormParam("number") int number) {
ObjectDTO c = new ObjectDTO();;
c.setNumber(number);
String generatedId = generateID();
c.setId(generatedId);
c.setOwner(sec.getUserPrincipal().getName());
return postAndGetResponse(c);
}
private Response postAndGetResponse(ObjectDTO object) {
Response res;
System.out.println(object);
if(ObjectDAO.instance.getObjectDao().containsKey(object.getId())) {
res = Response.serverError().status(409).build();
} else {
System.out.println(object);
System.out.println(object.getId());
String createdContent = create(object.getId());
System.out.println(createdContent);
res = Response.created(uriInfo.getAbsolutePath()).entity(createdContent).build();
ObjectDAO.instance.getObjectDao().put(object.getId(), object);
}
return res;
}
edit:
http://jersey.java.net/nonav/documentation/latest/jax-rs.html#d4e188
chapter 2.5
To create an entity tag simply call new EntityTag(string). But what are you trying to achieve in the code above? The entity tag should be attached to the header, not to the body.

Generic method, RESTful app

I'm using RESTful application in my java project. Normally in my unit test classes, I use methods like this:
public Employee getEmployeeByEmail(String email) {
ClientResponse clientResponse = webResource.path(beginPath + "getByEmail/" + email).get(
ClientResponse.class);
Employee employee = null;
if (200 == clientResponse.getStatus()) {
employee = clientResponse.getEntity(Employee.class);
}
return employee;
}
... but I have to use similar methods in almost 12 different classes. This is what I decided to do:
public class TestManager<T> {
private WebResource webResource;
private String beginPath;
private Class<T> clazz;
public TestManager(WebResource webResource, String beginPath, Class<T> clazz) {
this.webResource = webResource;
this.beginPath = beginPath;
this.clazz = clazz;
}
public boolean objectExists(String methodPath, String uniqueFieldName, String uniqueField) {
boolean check = false;
ClientResponse clientResponse = webResource.path(beginPath + methodPath + "/" + uniqueField).get(
ClientResponse.class);
JSONObject jsonObject = clientResponse.getEntity(JSONObject.class);
if (200 == clientResponse.getStatus() && !jsonObject.isNull(uniqueFieldName)) {
check = true;
}
return check;
}
public T getObjectById(String methodPath, long id) {
ClientResponse clientResponse = webResource.path(beginPath + methodPath + "/" + id).get(
ClientResponse.class);
T object = null;
if (200 == clientResponse.getStatus() && !clientResponse.getEntity(JSONObject.class).isNull("id")) {
object = clientResponse.getEntity(clazz);
}
return object;
}
}
The method objectExists() works fine, but getObjectById() method generate stack trace:
javax.ws.rs.WebApplicationException: javax.xml.bind.UnmarshalException: Error creating JSON-based XMLStreamReader - with linked exception:[javax.xml.stream.XMLStreamException: java.io.IOException: stream is closed]
It seems that I can't do this:
object = clientResponse.getEntity(clazz);
But I have no idea how to fix it. Sorry for my english :P
Edit:
Im using jersey
Edit2:
Solution:
The problem was I used getEntity() method twice ... If I use it only once ... it works ... damn it
It is a GET call. try calling it from a browser.
If that gives the same error, then there is nothing wrong with your client.
If you're having issues just with unit testing, then you might want to take a look at the Jersey Test Framework. Here's a link to the jersey docs on it, google can point you to further tutorials.

Categories

Resources