Request for help with Request Factory and Spring MVC integration

407 views
Skip to first unread message

Krishna Kishore k

unread,
Sep 28, 2011, 10:59:14 PM9/28/11
to google-we...@googlegroups.com
Hello,

Can anyone please help me out on the below? I am new to GWT and I have been trying a lot to get a starter app running using GWT, Spring and hibernate.

I was able to set up basic app but now I want to use RequestFactory with Spring MVC. After searching a lot I came across few links to get started but I am not able to completely figure out how to get the configuration right, and my app is not working :( . 

Can anyone please suggest me where I can get a sample app with RequestFactory and SpringMVC configured so that I can get the settings right. Or help me to get my app running. 


I am using GWT 2.4 and spring 3.

My web.xml is : 

<web-app>

<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>SimpleRPC.html</welcome-file>
</welcome-file-list>


<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Spring context -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- SpringGwt remote service servlet -->
<servlet>
<servlet-name>simpleRPC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>simpleRPC</servlet-name>
<url-pattern>/gwtspring/*</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>authServlet</servlet-name>
<servlet-class>org.spring4gwt.examples.simplerpc.server.AuthServiceImpl</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>authServlet</servlet-name>
<url-pattern>/gwtspring/auth</url-pattern>
</servlet-mapping>
</web-app>

simpleRPC-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/gwtspring=gwtRequestFactoryController
</value>
</property>
</bean>
<bean id="gwtSpringServiceLayerDecorator"
class="org.spring4gwt.examples.simplerpc.server.servlet.GWTSpringServiceLayerDecorator" />
<bean id="defaultExceptionHandler"
class="com.google.web.bindery.requestfactory.server.DefaultExceptionHandler" />
<!-- RequestFactoryServlet bean is scoped as singleton. Injecting custom 
SpringServiceLayerDecorator. -->
<bean id="requestFactoryServlet"
class="com.google.web.bindery.requestfactory.server.RequestFactoryServlet"
scope="singleton">
<constructor-arg ref="defaultExceptionHandler" />
<constructor-arg ref="gwtSpringServiceLayerDecorator" />
</bean>
<bean id="gwtSpringEntityLocator"
class="org.spring4gwt.examples.simplerpc.server.servlet.GWTSpringEntityLocator" />
<bean id="gwtSpringServiceLocator"
class="org.spring4gwt.examples.simplerpc.server.servlet.GWTSpringServiceLocator" />
<!-- IMPORTANT NOTE: CustomServletWrappingController is a hacked version 
of ServletWrappingController. The servlet class defined here will not be 
used. Please see CustomServletWrappingController for more information. -->
<bean id="gwtRequestFactoryController"
class="org.spring4gwt.examples.simplerpc.server.servlet.CustomServletWrappingController">
<property name="servletClass">
<value>com.google.web.bindery.requestfactory.server.RequestFactoryServlet
</value>
</property>
<property name="servletName">
<value>gwtspring</value>
</property>
</bean>
</beans>

EmployeeRequest.java

@Service(locator = GWTSpringServiceLocator.class, value = EmployeeRequest.class)
public interface EmployeeRequest extends RequestContext {

Request<EmployeeProxy> findEmployee(Long id);

InstanceRequest<EmployeeProxy, Void> persist();
}

EmployeeProxy .java

@ProxyFor(value = EmployeeDTO.class, locator = GWTSpringEntityLocator.class)
public interface EmployeeProxy extends EntityProxy {

String getEmployeeName();

String getEmployeeSurname();

Long getEmployeeId();

String getJob();

void setEmployeeName(String employeeName);

void setEmployeeSurname(String employeeSurname);

void setJob(String job);

void setEmployeeId(long employeeId);
}

EmployeeDTO.java

@Entity
@Table(name = "EMPLOYEE")
public class EmployeeDTO implements java.io.Serializable {
    
    private static final long serialVersionUID = 7440297955003302414L;

    @Id
    @Column(name="employee_id")
    private long employeeId;
    
    @Column(name="employee_name", nullable = false, length=30)
    private String employeeName;
    
    @Column(name="employee_surname", nullable = false, length=30)
    private String employeeSurname;
    
    @Column(name="job", length=50)
    private String job;
        
    public EmployeeDTO() {
    }

    public EmployeeDTO(int employeeId) {
        this.employeeId = employeeId;        
    }

    public EmployeeDTO(long employeeId, String employeeName, String employeeSurname,
            String job) {
        this.employeeId = employeeId;
        this.employeeName = employeeName;
        this.employeeSurname = employeeSurname;
        this.job = job;
    }

    public long getEmployeeId() {
        return employeeId;
    }

    public void setEmployeeId(long employeeId) {
        this.employeeId = employeeId;
    }

    public String getEmployeeName() {
        return employeeName;
    }

    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }

    public String getEmployeeSurname() {
        return employeeSurname;
    }

    public void setEmployeeSurname(String employeeSurname) {
        this.employeeSurname = employeeSurname;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

}

EmployeeService.java

public interface EmployeeService {
    
    public EmployeeDTO findEmployee(long employeeId);
 
    public void persist(EmployeeDTO employeeDTO);
}

EmployeeServiceImpl.java

@Service("employeeService") 
public class EmployeeServiceImpl implements EmployeeService{ 
    
    @Autowired 
    private EmployeeDAO employeeDAO; 

    @PostConstruct 
    public void init() throws Exception { 
    } 
    
    @PreDestroy 
    public void destroy() { 
    } 

    public EmployeeDTO findEmployee(long employeeId) { 
        
        return employeeDAO.findById(employeeId); 
        
    } 
    
    @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
    public void persist(EmployeeDTO employeeDTO) {
    if(employeeDTO == null) { 
            employeeDAO.persist(employeeDTO); 
        } 
      }


In my onModuleLoad method where I have the event for a button click on the page I am doing this

 EmployeeRequest request = requestFactory.employeeRequest();
 EmployeeProxy newEmployee = request.create(EmployeeProxy.class);

 Request<Void> createReq = request.persist().using(newEmployee);

 requestFactory.employeeRequest().findEmployee(employeeId).fire(
           new Receiver<EmployeeProxy>() {
             @Override
             public void onSuccess(EmployeeProxy employee) {
             System.out.println(employee.getEmployeeId());
             dialogBox.setText("Remote Procedure Call");
                   serverResponseLabel.removeStyleName("serverResponseLabelError");
                   serverResponseLabel.setHTML("OK");
                   dialogBox.center();
                   closeButton.setFocus(true);
             }
           });

The call for persist using request does not do anything. And the call to findEmployee throws a null pointer exception.

The locators I am using are attached in the mail. 

Please help me resolve this.


Thanks & Regards,
Kishore





CustomServletWrappingController.java
GWTSpringEntityLocator.java
GWTSpringServiceLayerDecorator.java
GWTSpringServiceLocator.java

-sowdri-

unread,
Sep 29, 2011, 1:49:50 AM9/29/11
to google-we...@googlegroups.com
>> http://jsinghfoss.wordpress.com/2011/08/10/gwt-2-2-0-requestfactory-spring-3-0-x-integration/ .

The solution presented in the above blog, suggests RF integration using DispatcherServlet, but there actually there is another way of integrating directly with your spring container. 

I'll put the solution here with as little code as possible. This will demonstrate

  1. BaseEntity (All entities extend this)
  2. Customer (Entity)
  3. CustomerProxy (EntityProxy/DTO)
  4. EntityLocator (Common to all Entities; a SpringBean)
  5. ServiceLocator (Common to all service; a SpringBean)
  6. AppServiceLayerDecorator (Extends ServiceLayerDecorator/enables RF to locate your EntityLocator which is a spring bean from the spring context)
  7. AppRequestFactoryServlet (To enable RF to use your AppServiceLayerDecorator)
  8. web.xml (To enable RF to use your AppRequestFactoryServlet instead of the default)
Note: I'm picking this from a larger project, which uses GWT 2.3/Hibernate/Postgres/Spring (without DispatcherServlet), if you are using 2.4 the CustomerProxy also could be made to extend BaseProxy on the client-side, I didn't do thtat at that time. Perhaps you can try..

BaseEntity


@MappedSuperclass
public abstract class Base implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Long id;

@Version
private Integer version;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public Integer getVersion() {
return version;
}

public void setVersion(Integer version) {
this.version = version;
}
}


Customer

@Entity
public class Customer extends Base {

String name;

Integer age;

// ...

}


CustomerProxy (EntityProxy/DTO)


@ProxyFor(value = Customer.class, locator = EntityLocator.class)
public interface CustomerProxy extends EntityProxy {

public Long getId();

public void setId(Long id);

public Integer getVersion();

public void setVersion(Integer version);

public String getName();

public void setName(String name);

public Integer getAge();

public void setAge(Integer age);

// ..
}


EntityLocator

@Service("entityLocator")
public class EntityLocator extends Locator<Base, Long> {

@PersistenceContext
EntityManager entityManager;

@Override
public Base create(Class<? extends Base> clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}

@Override
public Base find(Class<? extends Base> clazz, Long id) {
return entityManager.find(clazz, id);
}

@Override
public Class<Base> getDomainType() {
throw new UnsupportedOperationException();
}

@Override
public Long getId(Base domainObject) {
return domainObject.getId();
}

@Override
public Class<Long> getIdType() {
return Long.class;
}

@Override
public Object getVersion(Base domainObject) {
return domainObject.getVersion();
}
}


ServiceLocator 


public class AppServiceLocator implements ServiceLocator {

@Override
public Object getInstance(Class<?> clazz) {

HttpServletRequest request = RequestFactoryServlet
.getThreadLocalRequest();
ApplicationContext context = WebApplicationContextUtils
.getWebApplicationContext(request.getSession()
.getServletContext());
return context.getBean(clazz);
}
}

AppServiceLayerDecorator 

public class AppServiceLayerDecorator extends ServiceLayerDecorator {

@Override
public <T extends Locator<?, ?>> T createLocator(Class<T> clazz) {

HttpServletRequest request = RequestFactoryServlet
.getThreadLocalRequest();
ApplicationContext context = WebApplicationContextUtils
.getWebApplicationContext(request.getSession()
.getServletContext());

log.info("createLocator: " + clazz.getName());

return context.getBean(clazz);
}
// ...
}

AppRequestFactoryServlet 

public class AppRequestFactoryServlet extends RequestFactoryServlet {

private static final long serialVersionUID = -3364570784675688621L;

public AppRequestFactoryServlet() {
this(new DefaultExceptionHandler(), new AppServiceLayerDecorator());
}

public AppRequestFactoryServlet(ExceptionHandler exceptionHandler,
ServiceLayerDecorator... serviceDecorators) {
super(exceptionHandler, serviceDecorators);
}

}

web.xml


<servlet>
<servlet-name>requestFactoryServlet</servlet-name>
<servlet-class>in.verse.calldesk.server.AppRequestFactoryServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>requestFactoryServlet</servlet-name>
<url-pattern>/gwtRequest</url-pattern>
</servlet-mapping>

Note: Once you have got the above, you can create your DAO layer, and make them spring beans, and create corresponding RF RequestContext on the client, and use them using your AppServiceLocator!

This is a bigger concept, I've tried to put it all here. Hope this helps!

Krishna Kishore k

unread,
Sep 29, 2011, 4:17:47 AM9/29/11
to Google Web Toolkit

Hi,

I have implemented the above method you suggested.

But I am still facing the null pointer issue. I think I am doing
something wrong with the basics.

Instead of Using the DAO layer directly I am trying to implement use
the service layer in between.

The service class is

@Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService{

@Autowired
private EmployeeDAO employeeDAO;
@Transactional(propagation=Propagation.REQUIRED,
rollbackFor=Exception.class)
public void persist(EmployeeDTO employeeDTO) {
if(employeeDTO == null) {
employeeDAO.persist(employeeDTO);
}
}
}

the interface extended by the service is

public interface EmployeeService {
public void persist(EmployeeDTO employeeDTO);
}

The employee request class is

@Service(locator = AppServiceLocator.class, value =
EmployeeService.class)
public interface EmployeeRequest extends RequestContext {
InstanceRequest<EmployeeProxy, Void> persist();
}

and I am calling the persist method on the onclick event of a button
in the main html page.

But while debugging I dont find the request reaching the impl class.

Am I doing anything wrong?

Can you pls tell me if the /gwtRequest url pattern will be used by
default for all requests.

-sowdri-

unread,
Sep 29, 2011, 4:50:44 AM9/29/11
to google-we...@googlegroups.com
// this condition has to be reversed
if(employeeDTO == null) {
           employeeDAO.persist(employeeDTO);
 }


>> 
@Service(locator = AppServiceLocator.class, value = 
EmployeeService.class) 
public interface EmployeeRequest extends RequestContext { 
// this should not be instance request
Request<EmployeeProxy, Void> persist();  // correct
// InstanceRequest<EmployeeProxy, Void> persist();  // wrong



>> Can you pls tell me if the /gwtRequest url pattern will be used by 
default for all requests. 

Yes!

Krishna Kishore k

unread,
Sep 29, 2011, 5:08:30 AM9/29/11
to Google Web Toolkit
Using Request<EmployeeProxy, Void> persist();

I am getting compilation error saying "Incorrect number of arguments
for type Request<T>; it cannot be parameterized with arguments
<EmployeeProxy, Void>"

And I am calling the persist method as below.

/*MyRequestFactory.java*/
public interface MyRequestFactory extends RequestFactory {
EmployeeRequest employeeRequest();
}

/*SimpleRPC.java*/
private final MyRequestFactory requestFactory =
GWT.create(MyRequestFactory.class);
...
EmployeeRequest request = requestFactory.employeeRequest();
EmployeeProxy newEmployee = request.create(EmployeeProxy.class);
newEmployee.setId(employeeId);
...
Request<Void> createReq = request.persist().using(newEmployee);


Is the above way correct? I got that from the GWT documentation for
Request Factory
Message has been deleted

-sowdri-

unread,
Sep 29, 2011, 5:20:47 AM9/29/11
to google-we...@googlegroups.com
Sorry that was a typo,

@Service(locator = AppServiceLocator.class, value = 
EmployeeService.class) 
public interface EmployeeRequest extends RequestContext { 
// InstanceRequest<EmployeeProxy, Void> persist(); 
Request<Void> persist(EmployeeProxy employeeProxy); // this is right


and while calling, 

Request<Void> createReq = request.persist().using(newEmployee); // wrong

request.persist(newEmployee).fire(); // correct

I suggest you read the RF documentation!

Krishna Kishore k

unread,
Sep 29, 2011, 7:52:05 AM9/29/11
to Google Web Toolkit
I was not initializing the eventbus properly. After intializing it I
was able to continue and completed the RequestFactory Validation and
now my CRUD operations are working fine.

Thanks a lot for your help.. :)

-sowdri-

unread,
Sep 29, 2011, 8:17:16 AM9/29/11
to google-we...@googlegroups.com
Are you using the EntityLocator/AppServiceLayerDecorator/AppRequestFactoryServlet solution?

Krishna Kishore k

unread,
Sep 29, 2011, 12:31:57 PM9/29/11
to google-we...@googlegroups.com
Yes I am using the solution which you suggested in the first reply.. with EntityLocator/
AppServiceLayerDecorator/AppRequestFactoryServlet...

Reply all
Reply to author
Forward
0 new messages