Search
Calendar
October 2017
S M T W T F S
« Sep    
1234567
891011121314
15161718192021
22232425262728
293031  
Your widget title
Archives

PostHeaderIcon GWT: call a remote EJB with Spring lookup

Abstract

Let’s assume you have followed the article “Basic RPC call with GWT“. Now you would like to call an actual EJB 2 as remote, via a Spring lookup.
Let’s say: you have an EJB MyEntrepriseComponentEJB, which implements an interface MyEntrepriseComponent. This EJB, generates a remote MyEntrepriseComponentRemote.

Entry Point

In myApplication.gwt.xml entry point file, after the line:

<inherits name='com.google.gwt.user.User'/>

add the block:

  <inherits name='com.google.gwt.user.User' />
 <inherits name="com.google.gwt.i18n.I18N" />
 <inherits name="com.google.gwt.http.HTTP" />

Add the line:

<servlet path='/fooService.do'/>

Client

Under the *.gwt.client folder:

Update the service interface. Only the annotation parameter is amended:

@RemoteServiceRelativePath("services/fooService")
public interface FooService extends RemoteService {
 public String getHelloFoo(String fooName);
}

You have nothing to modify in asynchronous call interface (FooServiceAsync).

Server

Under the *.gwt.server folder, update the implementation for service interface:

Change the super-class, replacing RemoteServiceServlet with GWTSpringController:

public class FooServiceImpl extends GWTSpringController implements FooService {
 public FooServiceImpl() {
 // init
 }
}

Add new field and its getter/setter:

// retrieved via Spring
 private myEntrepriseComponent myEntrepriseComponent;

 public myEntrepriseComponent getMyEntrepriseComponent() {
 return myEntrepriseComponent;
 }

 public void setmyEntrepriseComponent(myEntrepriseComponent _myEntrepriseComponent) {
     myEntrepriseComponent = _myEntrepriseComponent;
 }

Write the actual call to EJB service:

 public String getHelloFoo(String fooName) {
    return myEntrepriseComponent.getMyDataFromDB();
 }
}

web.xml

Fill the web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
 PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

 <!-- Spring -->
 <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>

 <servlet>
    <servlet-name>gwt-controller</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
    <servlet-name>gwt-controller</servlet-name>
    <url-pattern>/myApplication/services/*</url-pattern>
 </servlet-mapping>

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

</web-app>

JNDI

Add a jndi.properties file in src/resources folder:

java.naming.provider.url=t3://localhost:12345
java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
java.naming.security.principal=yourLogin
java.naming.security.credentials=yourPassword
weblogic.jndi.enableDefaultUser=true

These properties will be used by Spring to lookup the remote EJB. The last option is very important, otherwise you may happen to face issues with EJB if they were deployed under WebLogic.

WEB-INF

In the WEB-INF folder, add an applicationContext.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<beans>

 <util:properties id="jndiProperties" location="classpath:jndi.properties" />

 <jee:remote-slsb id="myEntrepriseComponentService"
      jndi-name="ejb.jonathan.my-entreprise-component"
      business-interface="lalou.jonathan.myApplication.services.myEntrepriseComponent"
      environment-ref="jndiProperties" cache-home="false"
      lookup-home-on-startup="false" refresh-home-on-connect-failure="true" />

</beans>

Add a gwt-controller-servlet.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context.xsd">

 <bean>
    <property name="order" value="0" />
    <property name="mappings">
        <value>
            /fooService=fooServiceImpl
        </value>
     </property>
 </bean>

 <bean id="fooServiceImpl"
 class="lalou.jonathan.myApplication.web.gwt.server.FooServiceImpl">
      <property name="myEntrepriseComponent" ref="myEntrepriseComponentService" />
 </bean>
</beans>

Of course, if your servlet mapping name in web.xml is comoEstasAmigo, then rename gwt-controller-servlet.xml as comoEstasAmigo-servlet.xml 😉

Build and deploy

Now you can compile, package your war and deploy under Tomcat or WebLogic. WebLogic server may raise an error:
java.rmi.AccessException: [EJB:010160]Security Violation: User: '<anonymous>' has insufficient permission to access EJB
This error is related to the rights required to call a method on the EJB. Indeed, two levels of rights are used by WebLogic: firstly to lookup / instanciate the EJB (cf. the property java.naming.security.principal we set sooner), and another to call the method itself. In this second case, WebLogic requires an authentication (think of what you do when you login an web application deployed: your login and rights are kept for all the session) to grant the rights. I wish to handle this subject in a future post.

NB: thanks to David Chau and Didier Girard from SFEIR, Sachin from Mumbai team and PYC from NYC.

Leave a Reply