Jersey (JSR311-Implementation) & Redirections - java

Is there a way to redirect the user-agent in a Jersey Resource?
In Spring MVC there's the "redirect:"-syntax but I didn't find anything comparable in Jersey's Viewable class. The only method I found working was using HttpServletResponse.sendRedirect().

You have to return a Response object containing your status code and Location-header. The easiest way is to use javax.ws.rs.core.Response.temporaryRedirect(URI).
When using Viewable you might need to throw a WebApplicationException containing that Response object.

Related

How to have different JSON responses registered for a GET call

GET http://localhost/foo/api/v1/bars/:id
How to have different JSON responses registered for a GET call. We would like the GET call to return a separate response based on whether a CLI is invoking or the user interface is calling the API by passing a query parameter. But how do we register different serializers dynamically on the response.
You can use a User-Agent request header to identify the application doing the request. There are good tutorials to check how to access the headers in Spring, like this Baeldung one.

Jersey Viewable with Json

The JAX-RS implementation Jersey supports MVC style web applications through the Viewable class, which is a container for a template name and a model object. It is used like this:
#GET
#Template
#Produces({MediaType.TEXT_HTML})
public Viewable get() {
JsonObject response = null;
try{
response = service.getDetails(id);
}
catch(Exception ex) {
log.error("failed to get details", ex);
throw ex;
}
return new Viewable("/test", response);
}
this is right way to send the json from Viewable? Is there a way to set a json object explicitly?
A few things: I don't have any experience using Viewable in particular, but I am familiar with JAX-RS and can probably throw a couple of pointers your way.
Exception Handlers
JAX-RS defines a feature for mapping exceptions to responses. This functionality is nice for removing those exception blocks from your resource code. Check out the Jersey docs on this topic for a tutorial on how to register these. A quick summary is: 1) implement ExceptionMapper and 2) register the class as a Provider.
For starters, I recommend creating a simple suite that maps to common HTTP codes. For example:
NotFoundException - returns a 404 response and is used when a single entity is requested but not found.
InvalidInputException - returns a 422 response and is used when a request does not pass validation (like trying to save an phone number in an email field).
BadRequestException - usually the framework will handle these situations for you, but if not, a Bad Request is one that is not formatted properly. So if a required header is missing, or if a client tries to save a collection when only a single entity is allowed.
Exception* - There is a star here because an unexpected exception is usually due to a server error, so 500 is an appropriate default response. A reason you may want to create a global uncaught exception handler is to prevent the stacktrace from being returned in the response body. That can be bad for security reasons.
View and Model
You should not need the #Template annotation if you are using the Viewable object. Also, Viewable is expecting a template as the first argument and a model (map) as the second argument. The model should have keys that match variables in your JSP. Right now your method will look for a file called test.jsp in the root of whatever your template config is set to in web.xml. If you take all of that into consideration, your method could look something like this:
#GET
#Produces(MediaType.TEXT_HTML)
public Viewable getMobileReport() {
return new Viewable("/test", service.getMobileReport(id));
}

Any simple way to test a #RequestBody method?

If I have a #Controller method whose parameter is a #RequestBody param, I usually have to write some jQuery script or something similar to perform an AJAX request with JSON object in order to call that method. If I tried calling that method via a web browser directly, it returns with a Error 415 Unsupported Media Type.
Is there any alternative to just quickly call such method using browser without having to write some jQuery code? Like perhaps a way to write the JSON object in the URL/address bar?
code:
#RequestMapping("testCall")
#ResponseBody
public List<TestObject> getTestCall (#RequestBody TestParams testParams) {
return stuff;
}
public class TestParams {
private Integer testNumber;
//getter/setter for testNumber
}
I thought maybe I could just do:
http://localhost/testCall?testNumber=1
maybe Spring would auto populate a new TestParams instance with that property set to 1 but that didnt work...
maybe I need to do something extra for that?
The whole point of a #RequestBody annotated parameters is for the Spring MVC stack to use the HTTP request body to produce an argument that will be bound to the parameter. As such, you need to provide a request body. Sending a request body is very atypical for a GET request. As such, browsers don't typically support it, at least not when simply entering an address in the address bar and submitting the request.
You'll need to use a different HTTP client, like jQuery. I typically have a small Java project in Eclipse that's setup with an Apache HTTP components client which can send HTTP requests to whatever server. It takes a few seconds/minutes to setup the correct request body and run.
I have spent the last year building a REST API, and by far the best way to exercise that API manually is using the Chrome Extension, Postman. I cannot recommend this tool enough.
https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en
To test your simple example you'll need to invoke a POST (I assume that as you have a request body, but your controller method doesn't define a HTTP Verb) using POSTMAN to your Url (like the following example):
POST /contextRoot/testCall
{
"testNumber": 1
}
If you want to test your API automatically (which I recommend), you can use the excellent Spring Mvc Test project. This allows your to call your API via a rest-like DSL and assert that the response is in the shape you want. More details can be found here:
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/testing.html#spring-mvc-test-framework
you can add request params to the getTestCall method:
#RequestParam(value = "testNumber", required = false, defaultValue = "") String testNumber
There is a chrome app called Advanced REST client. You can pass the data in form of json to your controller using this chrome app. For eg. json data is
id:1,
name:"xyz"
whereas the controller can have #RequestBody Person form.
The Person class would be a POJO having id and name as instance variables. The Spring would automatically map the json data to the form.
I think this is the easiest and simplest way of checking your spring controller.
Check the extension Advanced REST client here
From what I know You can send JSON object to the webbrowser and it will be displayed without further need of AJAX.
useful tutorial:
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/

Get http response as a String using spring

is their a neat way to pass a model to jsp, render the jsp and return the html as string using Spring. The html is then used in an e-mail that is fired off programmitcally, I do not want to use freemarker, but maybe I should ?
The url being requested is part of the same app.
I want one of my service layer classes to be able to call a view and use the html as a String.
You can call requestDispatcher.include(request, response) method.
You will need to implement the request and response objects. The request object will provide all information to the dispatcher which page should be rendered, the response object you will pass to the call will then capture the result to a string (using e.g. a StringBuilder).
See e.g. this tutorial for more info.
I'm guessing a servlet filter will do the trick? Not really a Spring solution, but easy enough to do.
Also this answer seems relevant, although it is DWR that you may not necessarily want to use in this instance.
You can use Velocity to create an email template:
String text = VelocityEngineUtils.mergeTemplateIntoString(
velocityEngine, "emailTemplate.vm", model);
There is a complete chapter in the Spring reference docs of how Spring can be used to send emails of various types.

How to distinguish what format a client requests back to my REST webservice?

I have a Java WebService setup which consumes an xml file and want to be able to produce either xml or json based on what the client requests. I know that this is possible through reading up on Jersey REST methods but it does not show how to extract this information. I have also looked on google all over but can't seem to find any examples of this.
http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features is the site that I was initially referencing which shows that it is possible, I was just wondering if anyone would be able to help me find out how to actually distinguish the client's request. Is it in the html header? body? And if so what is the proper way to extract it?
This is what my method currently looks like, I do not have any issues with connection, just finding out what the client requests as a return type.
#POST
#Path("getStatisticData")
#Produces ({"application/xml","application/json"})
#Consumes ("application/xml")
public String getStatisticData(#FormParam("xmlCoords") String xmlFile) throws Exception{
Thanks in advance.
You can extract it using the #HeaderParam annotation:
...
public String getStatisticData(#HeaderParam("Accept") String accept,
#FormParam("xmlCoords") String xmlFile) throws Exception {
...
}
The Accept header in the request is used for the client to indicate to the server what methods it supports.
If the client can set HTTP headers, the proper way to do it is to use the Accept header:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
IF this is not possible, the type requested could be passed in as an argument.
Alternatively, expose two different web services: one that returns XML, one that returns JSON. Each web service would call the same code but with a parameter specifying which format to use.

Categories