Accepting request in Jersey webservice - java

Let us assume ,for my Jersey project somebody is trying to send a request in the form of a string(String is obtained by converting some json details like username and password).Is my java code capable to accept it?
#Path("/customers")
public class Authentication {
#POST
#Path("/get")
#Consumes(MediaType.APPLICATION_JSON)
public Response getRequestUrl(String JSON_DATA) {
System.out.println("inside Authentication");
// String output = s.toString();
return Response.status(201).entity(JSON_DATA).build();
}
If not how to accept a request for further processing.Can anybody gives its explanation(Especially about get and post method).Advance thanks

Yeah you should test it.
This is a working example from my testproject:
#POST
#Path("/post2")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces(MediaType.APPLICATION_JSON)
public Response addPerson(MultivaluedMap<String, String> map) {
// Dummy data
fillList();
Person person = new Person("Sample", 44);
// Get persons name and age from input fields
int age = Integer.parseInt(map.getFirst("age"));
String name = map.getFirst("name");
person = new Person(name, age);
lijst.add(person);
return Response.ok(person.toString()).build();
}
The service was online and I made an Android project to add a person to this list. It worked perfect :-)

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.

Use #POST instead of #GET to get user input

I am a newbie to JSON. I wish to ask that how can I convert the following code from #GET to #POST so that I can retrieve the appdataid from user JSON input and not from the link.
AppDataService ads = new AppDataService();
#GET
#Path("/{appdataid}")
#Produces(MediaType.APPLICATION_JSON)
public AppData getAppData(#PathParam("appdataid")long appdataid){
return ads.getAppData(appdataid);
}
Code for AppDataService
public AppDataService(){
appdatas.put(1L, new AppData(1,"Success", " ", "123456"));
appdatas.put(2L, new AppData(2,"Failure", " ", "654321"));
}
public AppData getAppData(long id){
return appdatas.get(id);
}
Instead of user entering http://localhost:8080/gni/webapi/appdata/1 for the result
{
"id": 1,
"message": " ",
"status": "Success",
"token": "123456"
}
I hope that I can receive the user input with #POST and JSON format.
I have tried the following code but not working.
#POST
#Path("/{appdataid}")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public AppData getAppData(#PathParam("appdataid")long appdataid){
return ads.getAppData(appdataid);
}
Thanks for everyone that willing to help me.
If you want to POST JSON to your resource, you need to define a POJO for it to deserialise the message body into, for example:
public class AppDataRequest {
#JsonProperty
private long id;
public long getId() {
return id;
}
}
The use this type for in the resource:
#POST
#Path("/")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public AppData getAppData(AppDataRequest appDataRequest){
return ads.getAppData(appDataRequest.getId());
}
Note, the #Path annotation no longer has appdataid templated, and the parameter does not have an annotation.
SIDE NOTE
I have to wonder what you are trying to achieve here. The HTTP methods can and should be used to help describe the behaviour of your system. A request to get data should use a GET resource. POST resources should be used for creating new data. Sometimes there are good reasons to break this convention (such as the lack of a message body in a GET request), but there are usually other ways around them. Everything about your example tells my it should be a GET request, but I do not know the specifics of you application, so feel free to ignore this if it does not apply.
I don't think you really need JSON for that. You can use #FormParam for such a simple payload (ID)
#POST
#Path("some_url")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)//optional
public AppData getAppData(#FormParam("appdataid")long appdataid){
return ads.getAppData(appdataid);
}
You can call your web service from a console (Jersey assumed)
WebTarget target = client.target(UriBuilder.fromUri("http://localhost:8088/Your_root_url").build());
try{
MultivaluedMap<String, Integer> formData = new MultivaluedHashMap<String, String>();
formData.add("appdataid", 1);
Response res= target.path("some_url").request().
post(Entity.entity(formData, MediaType.APPLICATION_FORM_URLENCODED));
AppData entity = (AppData) res.readEntity(AppData.class);
//System.out.println(entity);//if toString() is overriden
}catch(Exception e){
System.out.println(e);
return;
}
EDIT: The only reason I see for wanting to use a POST in this situation is securiry (and even that is arguable)

Dynamic result after error (List or Object)

That's my first question, and I've researched but didnt find the answer...
I'm currently developing a REST Webservice using Resteasy. Its working fine but I've come to a doubt: there is a way to return a List OR a Object ?
Let me exemplify: I've got a method to return a LIST of SECTORS that is called after passing a token of authentication.
If the token is OK - It should return the LIST of Sectors.
If the token is not OK - It should return an error which is mapped to a class called ErroGenerico that is an OBJECT.
How can I do that ? Return the OBJECT OR the LIST ?
Make a custom exception ErroGenerico and throw it if the token is not verified.
so, method:
public List<Something> getList(String token) throw ErroGenerico {
// do stuff
}
You can try as below
//Not mandatory to create ListUser you can do without it oo just use arraylist directly
class ListUser extends ArrayList<User> {}
webservice method
#GET
#Path("getObj/{param}")
#Produces("application/json")
public Response getObj(#PathParam("param") String msg) {
ListUser responses = new ListUser();
responses.add(new User("1"));
responses.add(new User("2"));
responses.add(new User("3"));
if("list".equals(msg))
return Response.status(200).entity(responses).build();
User u=new User();
u.setName("Developer");
return Response.status(200).entity(u).build();
}
Client code
Client client = ClientBuilder.newClient();
{
String url = "http://jerseyexample-ravikant.rhcloud.com/rest/jws/getObj/list";
System.out.println(url);
Response response = client.target(url).request().get();
ObjectMapper ob = new ObjectMapper();
Object pojos = response.readEntity(Object.class);
System.out.println(pojos.getClass());
if(pojos instanceof java.util.ArrayList){
ArrayList<User> list = (ArrayList) pojos;
for (Object pojo : list) {
User user = ob.convertValue(pojo, User.class);
System.out.println(user.getName());
}
}else{
System.out.println("user");
User user = ob.convertValue(pojos, User.class);
}
//System.out.println(response);
}
You can check working service at http://jerseyexample-ravikant.rhcloud.com/rest/jws/getObj/list
Here instead of passing list you can pass anything else to get object
In addition to this answer, I've found the article and it worked fine.
resteasy response

405 error returned when using POST method in Jersey

I'm using Jersey and have had no problem with GET and PUT calls but for some reason POST refuses to work; I keep getting a 405 returned.
I've tried multiple permutations for the signature on my method and I'm starting to wonder if there is something else I'm missing.
Here's an example of what won't work:
Server-side:
#Path("/tmm")
public class TmmRes {
#POST
#Path("/mypost")
#Consumes(MediaType.APPLICATION_JSON)
public Response postTest(String input) {
System.out.println("Made it to POST: "+input);
return Response.status(201).entity(input).build();
}
}
Client-side:
Client client = Client.create();
WebResource webResource = client.resource("http://localhost:8888/api/v1").path("tmm").path("mypost");
String input = "{\"address\":\"myaddress\",\"user\":4}";
ClientResponse response = webResource.type(MediaType.APPLICATION_JSON).post(ClientResponse.class, input);
I realize that using JSON I should have an object that the input binds to, but I've reduced the complexity to simply get the thing working.
Anybody have any insight? By the way, I'm using Tomcat (6.0.43).
I think you have to create a POJO like this:
public class User {
private String address;
private Integer user;
// getters and setters
}
and then change
#POST
#Path("/mypost")
#Consumes(MediaType.APPLICATION_JSON)
public Response postTest(String input) {
System.out.println("Made it to POST: "+input);
return Response.status(201).entity(input).build();
}
to:
#POST
#Path("/mypost")
#Consumes(MediaType.APPLICATION_JSON)
public Response postTest(User input) {
System.out.println("Made it to POST: "+input);
return Response.status(201).entity(input).build();
}
OK, with the help of a friend, I was able to figure this out. My URL was hitting a redirect. This was causing my POST to turn into a GET. Thanks for the help everyone. Your confirmations eliminated possibilities and helped guide me to the answer.
I solved this in IntelliJ.
Go to the menu: BUILD ->BUILD ARTIFACTS -> BUILD or REBUILD and that's it.

How to consume json parameter in java restful service

How can i consume json parameter in my webservice, I can able to get the parameters using #PathParam but to get the json data as parameter have no clue what to do.
#GET
#Path("/GetHrMsg/json_data")
#Consumes({ MediaType.APPLICATION_JSON })
#Produces(MediaType.APPLICATION_JSON)
public String gethrmessage(#PathParam("emp_id") String empid) {
}
What to use in place of #PathParam and how to parse it later.
I assume that you are talking about consuming a JSON message body sent with the request.
If so, please note that while not forbidden outright, there is a general consensus that GET requests should not have request bodies. See the "HTTP GET with request body" question for explanations why.
I mention this only because your example shows a GET request. If you are doing a POST or PUT, keep on reading, but if you are really doing a GET request in your project, I recommend that you instead follow kondu's solution.
With that said, to consume a JSON or XML message body, include an (unannotated) method parameter that is itself a JAXB bean representing the message.
So, if your message body looks like this:
{"hello":"world","foo":"bar","count":123}
Then you will create a corresponding class that looks like this:
#XmlRootElement
public class RequestBody {
#XmlElement String hello;
#XmlElement String foo;
#XmlElement Integer count;
}
And your service method would look like this:
#POST
#Path("/GetHrMsg/json_data")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public void gethrmessage(RequestBody requestBody) {
System.out.println(requestBody.hello);
System.out.println(requestBody.foo);
System.out.println(requestBody.count);
}
Which would output:
world
bar
123
For more information about using the different kinds of HTTP data using JAXB, I'd recommend you check out the question "How to access parameters in a RESTful POST method", which has some fantastic info.
Bertag is right about the comment on the GET. But if you want to do POST request that consumes json data, then you can refer to the code below:
#POST
#Path("/GetHrMsg/json_data")
#Consumes(MediaType.APPLICATION_JSON)
public Response gethrmessage(InputStream incomingData) {
StringBuilder crunchifyBuilder = new StringBuilder();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(incomingData));
String line = null;
while ((line = in.readLine()) != null) {
crunchifyBuilder.append(line);
}
} catch (Exception e) {
System.out.println("Error Parsing: - ");
}
System.out.println("Data Received: " + crunchifyBuilder.toString());
// return HTTP response 200 in case of success
return Response.status(200).entity(crunchifyBuilder.toString()).build();
}
For referencing please click here
#PathParam is used to match a part of the URL as a parameter. For example in an url of the form http:/example.com/books/{bookid}, you can use #PathParam("bookid") to get the id of a book to a method.
#QueryParam is used to access key/value pairs in the query string of the URL (the part after the ?). For example in the url http:/example.com?bookid=1, you can use #QueryParam("bookid") to get the value of `bookid.
Both these are used when the request url contains some info regarding the parameters and you can use the data directly in your methods.
Please specify the problem in detail if this post doesn't help you.

Categories

Resources