user1768830
user1768830

Reputation:

GWT hit HTTP servlet with RequestFactory

I want to use GWT's RequestFactory for all client-server communication, if possible. My understanding is that you have to map /gwtServlet to RequestFactoryServlet in your web.xml, and then use @Service annotations to tell the RequestFactoryServlet how to map client-side requests to their appropriate services.

Can someone provide a complete code example of this process, both on the client- and on the server-side? I'd like to send a Widget object from the client side to a WidgetProcessor service on the server-side:

public class Widget {
    // This is a domain object (POJO).
}

public class WidgetProcessor {
    public void processWidget(Widget w) {
        // Inspect the Widget. If certain properties contain certain
        // values, place it on a queue. Else "process" the Widget
        // and persist it to a DB.

        if(w.containsSpecialValues())
            QueueManager.sendToQueue(w);
        else {
            // Process widget...

            WidgetDAO.save(w);
        }
    }
}

In a non-GWT context, I would just define a WidgetProcessorServlet, map it to /processWidget, and make it look like:

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
    WidgetProcessor widgetProcessor = new WidgetProcessor();
    widgetProcessor.processWidget(getWidgetFromRequest(request));
}

How does this work in RequestFactory-land? Thanks in advance.

Upvotes: 8

Views: 1889

Answers (5)

Slava Dobromyslov
Slava Dobromyslov

Reputation: 3269

I've just developed a simple skeleton project for your purpose. Check my answer widget-processor on Github.

The project is based on Maven builder and the Java EE platform (GlassFish).

Project modules:

  1. ear - common ear module incorporates others in one EAR package which is easy to deploy;
  2. persistence - this module has only one file persistence.xml and links all external entities to one data source;
  3. ejb - this module has entity Widget and stateless EJB WidgetProcessor;
  4. web - general GWT module with RequestFactory.

Maven build process tuned to build everything properly. The project could be imported into IntelliJ Idea without any problems. And it could be debugged in Glassfish using standard Idea tools.

Also I have moved GWT RF and Persistence boilerplate code to external bilionix-core artifacts on Github.

Upvotes: 1

Sam
Sam

Reputation: 2747

Its possible with RequestFactories but its also possible with GWT-RPC. I prefer RequestFactories.

You will have a following classes and interfaces:

on server:

  1. Widget (Servlet)
  2. WidgetProcessor

on client:

  1. WidgetProxy
  2. WidgetRequest
  3. WidgetRequestFactory
  4. WidgetPresenter

WidgetServlet

package com.foo.bar.server;
public class Widget {
   //Your methods
    public void yourInstanceMethod(){
       //foo
    }
    public static void yourStaticMethod(){
       //bar
    }
    public static void processWidget(Widget w){
       WidgetProcessor widgetProcessor = new WidgetProcessor();
       widgetProcessor.processWidget(getWidgetFromRequest(request));
    }
}

WidgetProcessor

package com.foo.bar.server;
public class WidgetProcessor {
    public void processWidget(Widget w) {
        // Inspect the Widget. If certain properties contain certain
        // values, place it on a queue. Else "process" the Widget
        // and persist it to a DB.

        if(w.containsSpecialValues())
            QueueManager.sendToQueue(w);
        else {
            // Process widget...

            WidgetDAO.save(w);
        }
    }
}

WidgetProxy

package com.foo.bar.server;
import com.foo.bar.server.Widget;
@ProxyFor(value = Widget.class)
public interface WidgetProxy extends EntityProxy{
    //Your getter and Setter methods
}

WidgetRequest

package com.foo.bar.client;
import com.foo.bar.server.Widget;
@Service(value = Widget.class)
public interface WidgetRequest extends RequestContext{
    InstanceRequest<WidgetProxy, Void> yourInstanceMethod();
    Request<Void> yourStaticMethod();
    Request<Void> widgetProcessor(WidgetProxy widget);
}

WidgetRequestFactory

package com.foo.bar.client;
public interface WidgetRequestFactory extends RequestFactory{
    WidgetRequest widgetRequest();      
}

WidgetPresenter

package com.foo.bar.client;
public class WidgetPresenter {
    private final WidgetRequestFactory rf = GWT.create(WidgetRequestFactory.class);
    public WidgetPresenter() {
        rf.initialize(new EventBus());
        rf.widgetRequest().widgetProcessor().fire(new Receiver<Void>() {
            @Override
            public void onSuccess() {

                //Do what you want to confirm to user...
            }
        });
    }
}

Addtionally: If you responde the processed widget again to the User you would make it like this:

@Service(value = Widget.class)
public interface WidgetRequest extends RequestContext{
    ...
    Request<WidgetProxy> widgetProcessor(WidgetProxy widget);
}

public class Widget {
    ...
    public static void processWidget(Widget w){
       WidgetProcessor widgetProcessor = new WidgetProcessor();
       return widgetProcessor.processWidget(getWidgetFromRequest(request));
    }
}

public class WidgetProcessor {
    public Widget processWidget(Widget w) {
        // Inspect the Widget. If certain properties contain certain
        // values, place it on a queue. Else "process" the Widget
        // and persist it to a DB.

        if(w.containsSpecialValues())
            QueueManager.sendToQueue(w);
        else {
            // Process widget...

            WidgetDAO.save(w);
        }
        return w;
    }
}

public class WidgetPresenter {
    private final WidgetRequestFactory rf = GWT.create(WidgetRequestFactory.class);
    public WidgetPresenter() {
        rf.initialize(new EventBus());
        rf.widgetRequest().widgetProcessor().fire(new Receiver<WidgetProxy>() {
            @Override
            public void onSuccess(WidgetProxy response) {

                WidgetView v = new WidgedView(response);
                            RootPanel.get().add(view);
            }
        });
    }
}

package com.foo.bar.client;
public class WidgetView {


    public WidgetView(WidgetProxy widget) {

        //paint widget with widget
            // widget.getSomeProperty(); etc.

    }
}

Upvotes: 4

Suresh Atta
Suresh Atta

Reputation: 121998

I think no need to do Brain Storming with Request Factory for this purpose.

It can be very simple With Gwt RPC as per my opinion .

In short the simple RPC structure as below :

GWT Code <===> InterfaceAsync <===> Interface (Synchronous)<===> Server Code 

I am trying to explain with you elements it self .

The Synchronous Interface(central to the whole RPC):

import com.google.gwt.user.client.rpc.RemoteService;
public interface WidgetRPCInterface extends RemoteService
{
    public Widget widgetProcessRPC(Widget myWidget);
}

The ASynchronous Interface(Key part on Client):

import com.google.gwt.user.client.rpc.AsyncCallback;

public interface WidgetRPCInterfaceAsync
{
    public void widgetProcessRPCWidget myWidget, AsyncCallback callback);
}

Here you go with the Service(Equals to servlet) which implements "WidgetRPCInterface"

public class WidgetRPCImpl extends RemoteServiceServlet implements RPCInterface
{
    private static final long serialVersionUID = 1L;

    public Widget widgetProcessRPCWidget myWidget)
    {
       //Process your widget  here (CRUD operations)
       //You can change return type and return what ever you want to client . 
    }

**you can override doget,doPost,doDelete....etc along with your methods 
}

Map the above class in your web.xml;

     <servlet>
    <servlet-name>widgetrpc</servlet-name>
    <servlet-class>com.server.WidgetRPCImpl</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>widgetrpc</servlet-name>
    <url-pattern>/widgetrpc</url-pattern>
  </servlet-mapping>

Finally in your GWT Code .Use service as below

Using in Code:

//register the service .

   private final WidgetRPCInterfaceAsync widgetService = 
        GWT.create(WidgetRPCInterface.class);
        ServiceDefTarget endpoint = (ServiceDefTarget) service;
        endpoint.setServiceEntryPoint('widgetrpc');

requesting server with callback

widgetService.widgetProcessRPC(widgetFromClient, callback);
 AsyncCallback callback = new AsyncCallback()
    {
        public void onFailure(Throwable caught)
        {
           //Do on fail
        }

        public void onSuccess(Object result)
        {
           //Process successfully done with result (result is which you
           returned in impl class) .
        }
    };

P.S .Beware of package structures:

WidgetRPCInterfaceAsync ,WidgetRPCInterface should be in client* package

Widget class should be in shared* package

WidgetRPCImpl should be in server* package

And Have a look on RPC Example

Upvotes: 3

appbootup
appbootup

Reputation: 9537

You are a bit confused about RequestFactory scenarios.

You need to start here - https://developers.google.com/web-toolkit/doc/latest/DevGuideRequestFactory

Browse Sample RequestFactory demo @ DynatableRF code - http://code.google.com/p/google-web-toolkit/source/browse/#svn/trunk/samples/dynatablerf

Download Sample RequestFactory demo @ DynatableRF code - http://google-web-toolkit.googlecode.com/files/gwt-2.5.0.zip

Edit - RequestFactory examples get convoluted with MVP, Activities and Editor Framework. A great deal of effort would be required to conclude which combination of RF, Editor, MVP & Activties you would need with your scenarios.

Upvotes: 4

Andy King
Andy King

Reputation: 1662

Your Widget class will be on the server-side. On the client-side you will use an interface to represent a Widget; this interface will be a proxy for the actual Widget object. You associate the proxy interface with the class using the @ProxyFor annotation. For example, if you have the Widget class on the server, you could have the WidgetProxy interface on the client:

@ProxyFor(value = Widget.class)
public interface WidgetProxy extends EntityProxy {
}

The proxy contains getters and setters for the properties of the entity, and those getters and setters are mirrored in the class on the server. Request factory also needs a way to locate the class that the proxy is associated with, and I use a "locator" class for this (although there are other approaches). The locator is also specified in the @Proxy annotation:

@ProxyFor(value = Widget.class, locator = WidgetLocator.class)

The WidgetLocator class is also on the server side. For each Widget that you want to insert or update you will need to create a RequestContext. The RequestContext identifies the methods that will operate against the entity. The actual implementation of those methods is again on the server side ... you can either introduce a separate class containing the methods, or add them to the entity class (Widget in your case). I prefer to separate them into a "DAO" class, limiting the entity class (i.e., Widget) to a simple bean. (Your DAO class is named WidgetProcessor). The RequestContext on the client side is an interface that extends the RequestContext interface. Your RequestContext interface tells request factory where to find the DAO on the server, and that's where you use the @Service annotation.

Take a look at Thomas Broyer's blog for a good introduction: GWT 2.1.1 RequestFactory. I also found the book GWT in Action (Second Edition) a useful resource. I created an example based upon my learning experience, which may also be useful to you: A GWT Request Factory Journey; again, this may or may not be useful!

Upvotes: 1

Related Questions