Integrating GWT with Spring - java

I know that this topic was discussed many times, but I found that the most of information on this is not up to date.
I am looking for tutorial/example on how to integrate GWT with Spring framework.
I have found many examplex (some of them even working), but only with older libraries. I am looking for a solution with newest libraries (or at least compatible with the newest).
Also many examples use spring4gwt library (for creating "glue" servlet) - is there another way?
I want to create simple example application using GWT + Spring + Hibernate + Maven. I started by creating Web Application Project (from Eclipse). I converted project to Maven project. And to be honest I am stuck here. I can create simple service (+ async), but have no idea how to configure proper servlet and go further. Examples I found relay on spring4gwt, but I would like not to use it (no new version since 2009 I think).
It would be great if someone could explain integration step-by-step.
Sorry if this one is a duplicate, but after long search I haven't found clear solution that suits my needs.

You have many ways to integrate with Spring, but i think the best option is use RestyGWT Framework
Since you are using HTTP protocol and JSON format for serializing objects, you won't have problem to comunicate with the Spring Controllers using RestyGWT.
You could also use your own controllers to respond to GWT RPC Requests. Instead of using GWT Dispatcher, you use the Spring MVC Request Dispacher and map the URLS on controllers to your services in GWT client.
if you use the RESTY GWT API, you could just write your interface, map the methods using JAX-RS annotations like #POST, #GET, #DELETE, #PathParam, etc.
Here's what I'm doing on my project using RestyGWT:
The project is compose of 2 projects:
project-client
project-server
The client contains all files related to GWT and RestyGWT.
The server contains all files from the back end implementation using Spring.
Maven overlay is used to merge the 2 projects on the package compile phase, so you end with a final war with the GWT *js files and the server files.
To use RestyGWT you have to create an interface who extends RestService:
public interface MyRestService extends RestService{
#GET
#Path("/foo")
public void getFoo(MethodCallback<List<Foo>);
#POST
#Path("/foo")
public void saveFoo(Foo foo ,MethodCallback<MessageResponse>);
}
To use the service you write something like this:
MyRestService service = GWT.create(MyRestService.class);
and you will have something like this to use the service:
service.getFoo(new MethodCallBack<List<Foo>>(){
public void onSucess(List<Foo> foos){
/* You will get foos, you dont have to worry about serialization, RESTYGWT does it for you */
}
public void onError() ...
});
And you will have a controller to respond to this request like this:
#Controller
class myController{
#Autowired FooService svc;
#RequestMapping(value = "/foo", method = RequestMethod.GET, produces= "application/json")
public #ResponseBody List<Foo> getAllFoos(){
return svc.all();
}
#RequestMapping(value = "/foo", method = RequestMethod.POST, produces= "application/json", consumes="application/json")
public #ResponseBody MessageResponse save(#ResponseBody Foo foo){
svc.save(foo);
return new MessageResponse("Foo saved with sucess", 200);
}
}

I've created many projects with this setup, you don't need spring4gwt!
My solution is to use a "bridge" class that allow you to call async services like spring controllers:
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.servlet.ModelAndView;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
public abstract class BaseRemoteService extends RemoteServiceServlet implements
ServletContextAware {
private static final long serialVersionUID = 2470804603581328584L;
protected Logger logger = Logger.getLogger(getClass());
private ServletContext servletContext;
#RequestMapping(method = { RequestMethod.GET, RequestMethod.POST })
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
doPost(request, response);
return null; // response handled by GWT RPC over XmlHttpRequest
}
#Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
#Override
public ServletContext getServletContext() {
return this.servletContext;
}
}
Now, your *RpcServiceImpl should be something like:
#Controller
#RequestMapping("/*/action.service")
public class ActionRpcServiceImpl extends BaseRemoteService implements ActionRpcService {
//this class is managed by spring, so you can use #Autowired and other stuffs
//implementation of your rpc service methods,
}

Related

How to use Jersey's internal routing mechanism to extract a class/method reference?

I have a Jersey 1.8 application running. Jersey is running as a Servlet.
I need to write a servlet filter that given a plain request/response, is able to figure out which REST resource/method will respond to the request and extract values from annotations.
For example, imagine I have the following resource:
#Path("/foo")
#MyAnnotation("hello")
public class FooResource {
#GET
#Path("/bar")
#MyOtherAnnotation("world")
public Response bar(){
...
}
}
When a request GET /foo/bar comes in, I need my servlet filter to be able to extract the values "hello" and "world" from MyAnnotation and MyOtherAnnotation before Jersey's own servlet processes the request.
This filter logic should be able to work for all requests and all resources registered.
Is there a way to access Jersey's internal routing mechanism to obtain a class/method reference where Jersey will dispatch the request?
I'm open to other suggestions as well, but ideally nothing like trying to hack my own routing mechanism by reading the #Path annotations myself.
#Provider
#Priority(Priorities.AUTHORIZATION)
public class MyFilter implements ContainerRequestFilter
#Context // request scoped proxy
private ResourceInfo resourceInfo;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
if (resourceInfo.getResourceClass().isAnnotationPresent(MyAnnotationion.class) ||
resourceInfo.getResourceMethod().isAnnotationPresent(MyOtherAnnotation.class)) {
to register the filter use
bind(AuthFilter.class).to(ContainerRequestFilter.class).in(Singleton.class);

Using PATCH with Jersey Client API for unit testing

I am working on a REST API implementation using Jersey. For PATCH (partial updates), I have implemented my own custom implementation of PATCH since Jersey does not support it.
Now I am trying to figure out how to write functional tests around that implementation. I am using jersey test framework for other methods (PUT, POST, GET, DELETE) that has that support available in that framework.
Is there a way where in I can extend jersey test framework implementation to write my functional tests for PATCH?
If not, are there any other test frameworks available that I can use to test my Jersey PATCH implementation?
If anyone can provide any examples, that would be great.
Assuming your implementation consists of a custom annotation like this
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.ws.rs.HttpMethod;
#HttpMethod("PATCH")
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface PATCH {}
Trying to do something like this with the Client
String response = target.request().method("PATCH", Entity.text("Hello"), String.class);
by default is not supported, and will an exception like
java.net.ProtocolException: Invalid HTTP method: PATCH
This is not a problem with the Client API directly, but with the lower level Java APIs. Seems to be some security restriction.
With the Client API we can override this by setting a property
HttpUrlConnectionProvider.SET_METHOD_WORKAROUND to true
In the JerseyTest, one way to configure the Client is to override configureClient, and set the property with the ClientConfig. You could just as easily set the property on the Client itself, but staying in the spirit of the JerseyTest framework (where we don't need to explicitly access the Client, the example below will just just override the method
public class PatchTest extends JerseyTest {
#Path("patch")
public static class PatchResource {
#PATCH
#Produces(MediaType.TEXT_PLAIN)
public String getPatch(String request) {
return "Patched " + request;
}
}
#Override
protected void configureClient(final ClientConfig config) {
config.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true);
}
#Override
public Application configure() {
return new ResourceConfig(PatchResource.class);
}
#Test
public void doPatchTest() {
WebTarget target = target("patch");
String response = target.request().method("PATCH", Entity.text("Hello"), String.class);
Assert.assertEquals("Patched Hello", response);
System.out.println(response);
}
}
To send the HTTP PATCH via JAX RS Client API without any extra configuration:
client.target("$baseUrl$restUsersUrl/$userId")
.request("application/json")
.build("PATCH", Entity.entity(json2Update, MediaType.APPLICATION_JSON))
.invoke()
Annotation #PATCH is now available in JAX-RS 2.1. You can implement this HTTP method on the server side like:
#PATCH
public Response updateResource() { ... }
As for the client side, you can do something like:
Response r = ClientBuilder.newClient()
.target("http://localhost:8080/patch")
.request()
.build("PATCH", Entity.text("patch"))
.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true)
.invoke();
Where SET_METHOD_WORKAROUND is used to avoid the protocol exception, as indicated by #peeskillet:
java.net.ProtocolException: Invalid HTTP method: PATCH
With simple Strings this works for me. But does anyone know how to do this when the Patch method does not accept and return a simple String? See my example below.
The return type in the Response differs from the type of the passed argument. Both of which are not simple types.
Instead of a 200, I always get a 400 and/or the message that it cannot construct the ObjectPatch instance. And I understand that, since it is an interface with only an apply method. But somehow on runtime it manages to construct an AttentionPatchResource object from it anyway. Unfortunately not when using the JerseyTest framework.
#PATCH
#Path("/something")
#Produces(MediaType.APPLICATION_JSON)
#Consumes({ PatchMediaTypes.APPLICATION_MERGE_PATCH_JSON, PatchMediaTypes.APPLICATION_JSON_PATCH })
public Response updateAttention( //
#Parameter(schema = #Schema(implementation = AttentionPatchResource.class)) ObjectPatch patch) {
Attention attention = attentionService.find();
AttentionPatchResource patchResource = attentionAdapter.toPatchResource(attention);
AttentionPatchResource patchedResource = patch.apply(patchResource);
Attention patchedAttention = attentionAdapter.fromPatchResource(attention, patchedResource);
AttentionResource resource = attentionAdapter.toResource(patchedAttention);
return Response.status(Status.OK).entity(resource).build();
}

Set JAX-RS response headers in implementation without exposing HttpServletResponse in interface

I have a RESTful server implementation as well as a library for clients to make the calls, all using JAX-RS. The server components are divided up into interface FooResource and implementation FooResourceService.
In order for the client and server libraries to share RESTful path and other definitions, I wanted to split out the FooResource interface into its own project:
#Path(value = "foo")
public interface FooResource {
#GET
public Bar getBar(#PathParam(value = "{id}") int id) {
I want to set some headers in the response. One easy way to do this is to use #Context HttpServletResponse in the method signature:
public Bar getBar(#PathParam(value = "{id}") int id, #Context HttpServletResponse servletResponse) {
But the problem is that this exposes implementation details in the interface. More specifically, it suddenly requires my REST definition project (which is shared between the client and server library) to pull in the javax.servlet-api dependency---something the client has no need up (or desire for).
How can my RESTful resource service implementation set HTTP response headers without pulling in that dependency in the resource interface?
I saw one post recommending I inject the HttpServletResponse as a class member. But how would this work if my resource service implementation is a singleton? Does it use some sort of proxy with thread locals or something that figures out the correct servlet response even though the singleton class is used simultaneously by multiple threads? Are there any other solutions?
The correct answer seems to be to inject an HttpServletResponse in the member variable of the implementation, as I noted that another post had indicated.
#Context //injected response proxy supporting multiple threads
private HttpServletResponse servletResponse;
Even though peeskillet indicated that the semi-official list for Jersey doesn't list HttpServletResponse as one of the proxy-able types, when I traced through the code at least RESTEasy seems to be creating a proxy (org.jboss.resteasy.core.ContextParameterInjector$GenericDelegatingProxy#xxxxxxxx). So as far as I can tell, thread-safe injection of a singleton member variable seems to be occurring.
See also https://stackoverflow.com/a/10076327/421049 .
So injecting HttpServletResponse seems like a no go. Only certain proxy-able types are inject-able into singletons. I believe the complete list is as follows:
HttpHeaders, Request, UriInfo, SecurityContext
This is somewhat pointed out in the JAX-RS spec, but is explained more clearly in the Jersey reference guide
The exception exists for specific request objects which can injected even into constructor or class fields. For these objects the runtime will inject proxies which are able to simultaneously server more request. These request objects are HttpHeaders, Request, UriInfo, SecurityContext. These proxies can be injected using the #Context annotation.
SecurityContext may be Jersey specific, as it's not stated in the spec, but I'm not sure.
Now those types mentioned above don't really do much for you because they are all request contexts and nothing to set the response.
One Idea though is to use a javax.ws.rs.container.ContainerResponseFilter, along with the HttpHeaders to set a temporary request header. You can access that header through the ContainerRequestContext passed to the filter method. Then just set the response header through the ContainerResponseContext, also passed to the filter method. If the the header is not specific to the context of that resource method, then it's even easier. Just set the header in the filter.
But let's say the header is dependent on the execution of the resource method. Then you could do something like
#Singleton
#Path("/singleton")
public class SingletonResource {
#Context
javax.ws.rs.core.HttpHeaders headers;
#GET
public String getHello() {
String result = resultFromSomeCondition(new Object());
headers.getRequestHeaders().putSingle("X-HELLO", result);
return "Hello World";
}
private String resultFromSomeCondition(Object condition) {
return "World";
}
}
Then the ContainerResponseFilter might look something like this
#Provider
public class SingletonContainerResponseFilter
implements ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext crc,
ContainerResponseContext crc1) throws IOException {
String header = crc.getHeaderString("X-HELLO");
crc1.getHeaders().putSingle("X-HELLO", "World");
}
}
And just so only the singleton classes run through this filter, we can simply use a #NameBinding annotation
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.ws.rs.NameBinding;
#NameBinding
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface SingletonHeader {}
...
#SingletonHeader
public class SingletonResource {
...
#SingletonHeader
public class SingletonContainerResponseFilter
implements ContainerResponseFilter {
This is the only way I can think to handle this situation.
Resources:
Filters and Interceptors
Name Binding
#Path("/foo")
public interface FooResource {
#GET
#Path("{id}")
public Response getBar(#PathParam("id") int id) {
Bar bar = new Bar();
//Do some logic on bar
return Response.ok().entity(bar).header("header-name", "header-value").build()
}
}
Returns a JSON representation of the instance of bar with a status code 200 and header header-name with value header-value. It should look something along the lines of:
{
"bar-field": "bar-field-value",
"bar-field-2": "bar-field-2"
}

How can a JAX-RS REST service have authentication handled by annotations?

I have a REST api written with JAX-RS, and I need to add authentication to it. So far all the information I've been able to find about it has suggestions for doing it via spring, which I'm not using. Is there something already existing, or would it be easy to write, something that will let me annotate either a method, or the entire class which would force auth headers to be present?
I'm using tomcat6 and jersey, if that matters.
Something like:
#Path("api")
public class Api {
#GET
#AuthenticationRequired
public Response getInfo(...) {...}
}
I think you want import javax.annotation.Security.RolesAllowed;
The annotation itself looks like this
#Path("/helloworld")
#RolesAllowed({"ADMIN", "ORG1"})
public class helloWorld {
#GET
#Path("sayHello")
#Produces("text/plain")
#RolesAllowed("ADMIN")
public String sayHello() {
return "Hello World!";
}
}
I would manage security at the container level. Here's a good writeup if you happen to be using Apache CXF:
http://cxf.apache.org/docs/secure-jax-rs-services.html
And here's an example for Glassfish:
http://www.butonic.de/2010/06/18/a-simple-jax-rs-security-context-example-in-glassfish/
Here's one more link, which discusses JSR 250 annotations (e.g. #RolesAllowed):
http://www-01.ibm.com/support/knowledgecenter/SSEQTP_8.5.5/com.ibm.websphere.base.doc/ae/twbs_jaxrs_impl_securejaxrs_annotations.html

Spring SimpleFormController in 3.0

i notice that this controller has now been deprecated in the latest spring and was wondering what the alternative controller is?
In Spring 3.0 you should use simple classes annotated by #Controller. Such controller can handle more than one request. Each request is handled by its own method. These methods are annotated by #RequestMapping.
One thing you need to rethink is the fact, that a old school SimpleFormController handle a lot of different requests (at least: one to get the form and a second to submit the form). You have to handle this now by hand. But believe me it is easier.
For example this Controller in REST Style, will handle two requests:
/book - POST: to create a book
/book/form - GET: to get the form for creation
Java Code:
#RequestMapping("/book/**")
#Controller
public class BookController {
#RequestMapping(value = "/book", method = RequestMethod.POST)
public String create(
#ModelAttribute("bookCommand") final BookCommand bookCommand) {
Book book = createBookFromBookCommand(bookCommand);
return "redirect:/book/" + book.getId();
}
#RequestMapping(value = "/book/form", method = RequestMethod.GET)
public String createForm(final ModelMap modelMap) {
modelMap.addAttribute("all", "what you need");
return "book/create"; //book/create.jsp
}
}
Annotated POJOs can act as controllers; see #Controller.
In Spring 3.0, your Controllers should no longer inherit from a base class.
The standard way is to use annotated controllers.

Categories