Thursday, December 28, 2006

Spring Security with Acegi Security

Acegi Security provides a comprehensive security solution for J2EE-based enterprise software applications, built using the Spring Framework. Acegi provides authentication service through the use of a web filter, an AuthenticationProvider and an AuthenticationEntryPoint. Authorization in Acegi can be done at different levels: authorizing web requests, authorizing which methods can be invoked, and authorizing access to individual domain object instances. In this example I will describe how to implement form-based authentication and URL level authorization using Acegi.
For this example, I use two secure JSPs, the secure/authenticatedusers.jsp file is available to all the authenticated users, and secure/admin/admin.jsp is only available to the users with ADMIN role. The login.jsp is used for login and denied.jsp is used to redirect unauthorized users. Follow these steps to run the example:
  1. Download Acegi and Spring.
  2. Start with a dynamic web project in eclipse.
  3. Copy the following Jar files into the WEB-INF/lib directory.
    acegi-security-1.0.3.jarMain classes of the Acegi security system.
    commons-codec-1.3.jarEncoders and decoders such as Base64, Hex, Phonetic and URLs.
    ehcache-1.2.3.jarUsed by the authentication provider.
    jstl.jar, standard.jarThe JSTL tag library
    spring.jarSpring framework
    commons-logging.jar, cglib-nodep-2.1_3.jarAvailable in the spring download (spring with dependencies)
  4. Create the Login page: The following is a listing for the login page.
    <jsp:root version="1.2" xmlns:jsp="http://java.sun.com/JSP/Page"
    xmlns:c="urn:jsptld:http://java.sun.com/jsp/jstl/core">
    <jsp:directive.page contentType="text/html; charset=UTF-8" />
    <jsp:directive.page
    import="org.acegisecurity.ui.AbstractProcessingFilter, org.acegisecurity.ui.webapp.AuthenticationProcessingFilter, org.acegisecurity.AuthenticationException" />
    <head>
    <title>Login</title>
    </head>
    <body>
    <form action="j_acegi_security_check" method="POST">
    <table>
    <tr>
    <td>User:</td>
    </td><input type='text' name='j_username' />
    </td>
    </tr>
    <tr>
    <td>Password:</td>
    <td><input type='password' name='j_password' /></td>
    </tr>
    <tr>
    <td><input type="checkbox" name="_acegi_security_remember_me" /></td>
    <td>Remember me (14 days)</td>
    </tr>
    <tr><td colspan='2'><input name="submit" type="submit" /></td></tr>
    <tr><td colspan='2'><input name="reset" type="reset" /></td></tr>
    </table>
    </form>
    </body>
    </jsp:root>
    login.jsp

    Notes:
    • The login form uses j_acegi_security_check instead of j_security_check normally used for form-based authentication. Similarly for logout, we use j_acegi_logout action.
    • In order to remember a user for a period of time, use the _acegi_security_remember_me attribute. This is configured in the applicatonContext.xml file(see below).
  5. Create the other JSP files: The listings for the JSP pages used for this example are shown below, along with their respective directories.
    <html>
    <body>
    Everyone
    <p><a href="secure/authenticatedusers.jsp">Authenticated users only</a>
    <p><a href="secure/admin/admin.jsp">Admins only</a>
    </body>
    </html>
    index.jsp
    Access Denied.
    denied.jsp
    <%@ page import="org.acegisecurity.context.SecurityContextHolder" %>
    <h1>Welcome: <%= SecurityContextHolder.getContext().getAuthentication().getName() %></h1>
    <p><a href="../">Home</a>
    <p><a href="../j_acegi_logout">Logout</a>
    secure/authenticatedusers.jsp
    <%@ page import="org.acegisecurity.context.SecurityContextHolder" %>
    <h1>Welcome: <%= SecurityContextHolder.getContext().getAuthentication().getName() %> is an Admin</h1>
    <p><a href="../../">Home</a>
    <p><a href="../../j_acegi_logout">Logout</a>
    </body>
    </html>
    secure/admin/admin.jsp
  6. The users.properties file: This example uses an in memory user registry and the WEB-INF/users.properties file is used to store the usernames and passwords.
    scott=tiger,ROLE_USER
    harry=potter,ROLE_ADMIN
    frodo=baggins,ROLE_USER
    WEB-INF/users.properties
  7. Configure the Acegi filter in the Web deployment descriptor: The web.xml file is shown below
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>SpringSecurity</display-name>

    <filter>
    <filter-name>Acegi Filter Chain Proxy</filter-name>
    <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
    <init-param>
    <param-name>targetClass</param-name>
    <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
    </init-param>
    </filter>

    <filter-mapping>
    <filter-name>Acegi Filter Chain Proxy</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

    <listener>
    <listener-class>
    org.springframework.web.context.ContextLoaderListener
    </listener-class>
    </listener>

    <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
    </web-app>
    web.xml
  8. Configure Acegi in applicationContext.xml file: The following is a listing of the WEB-INF/applicationContext.xml file, followed be explanations of the different beans defined in there.
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>

    <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
    <property name="filterInvocationDefinitionSource">
    <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
    </value>
    </property>
    </bean>

    <bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>

    <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
    <constructor-arg value="/index.jsp"/>
    <constructor-arg>
    <list>
    <ref bean="rememberMeServices"/>
    <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
    </list>
    </constructor-arg>
    </bean>

    <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="authenticationFailureUrl" value="/login.jsp?errorId=1"/>
    <property name="defaultTargetUrl" value="/"/>
    <property name="filterProcessesUrl" value="/j_acegi_security_check"/>
    <property name="rememberMeServices" ref="rememberMeServices"/>
    </bean>

    <bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"/>

    <bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="rememberMeServices" ref="rememberMeServices"/>
    </bean>

    <bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
    <property name="key" value="changeThis"/>
    <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
    </bean>

    <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
    <property name="authenticationEntryPoint">
    <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
    <property name="loginFormUrl" value="/login.jsp"/>
    <property name="forceHttps" value="false"/>
    </bean>
    </property>
    <property name="accessDeniedHandler">
    <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
    <property name="errorPage" value="/denied.jsp"/>
    </bean>
    </property>
    </bean>

    <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="accessDecisionManager">
    <bean class="org.acegisecurity.vote.AffirmativeBased">
    <property name="allowIfAllAbstainDecisions" value="false"/>
    <property name="decisionVoters">
    <list>
    <bean class="org.acegisecurity.vote.RoleVoter"/>
    <bean class="org.acegisecurity.vote.AuthenticatedVoter"/>
    </list>
    </property>
    </bean>
    </property>
    <property name="objectDefinitionSource">
    <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /secure/admin/**=ROLE_ADMIN
    /secure/**=IS_AUTHENTICATED_REMEMBERED
    /**=IS_AUTHENTICATED_ANONYMOUSLY
    </value>
    </property>
    </bean>

    <bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
    <property name="userDetailsService" ref="userDetailsService"/>
    <property name="tokenValiditySeconds" value="1800"></property>
    <property name="key" value="changeThis"/>
    </bean>

    <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
    <property name="providers">
    <list>
    <ref local="daoAuthenticationProvider"/>
    <bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
    <property name="key" value="changeThis"/>
    </bean>
    <bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
    <property name="key" value="changeThis"/>
    </bean>
    </list>
    </property>
    </bean>

    <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
    <property name="userDetailsService" ref="userDetailsService"/>
    <property name="userCache">
    <bean class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
    <property name="cache">
    <bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
    <property name="cacheManager">
    <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
    </property>
    <property name="cacheName" value="userCache"/>
    </bean>
    </property>
    </bean>
    </property>
    </bean>

    <bean id="userDetailsService" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
    <property name="userProperties">
    <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="location" value="/WEB-INF/users.properties"/>
    </bean>
    </property>
    </bean>

    <bean id="loggerListener" class="org.acegisecurity.event.authentication.LoggerListener"/>

    </beans>
    WEB-INF/applicationContext.xml
    1. FilterChainProxy: Delegates Filter requests to a list of Spring-managed beans.
    2. HttpSessionContextIntegrationFilter: Populates the SecurityContextHolder with information obtained from the HttpSession.
    3. LogoutFilter: Logs a principal out.
    4. AuthenticationProcessingFilter: Processes an authentication form.
    5. SecurityContextHolderAwareRequestFilter: A Filter which populates the ServletRequest with a new request wrapper.
    6. RememberMeProcessingFilter: Detects if there is no Authentication object in the SecurityContext, and populates it with a remember-me authentication token if a RememberMeServices implementation so requests.
    7. AnonymousProcessingFilter: Detects if there is no Authentication object in the SecurityContextHolder, and populates it with one if needed.
    8. AnonymousProcessingFilter: Detects if there is no Authentication object in the SecurityContextHolder, and populates it with one if needed.
    9. ExceptionTranslationFilter: Handles any AccessDeniedException and AuthenticationException thrown within the filter chain.
    10. AuthenticationProcessingFilterEntryPoint: Used by the SecurityEnforcementFilter to commence authentication via the AuthenticationProcessingFilter. This object holds the location of the login form, relative to the web app context path, and is used to commence a redirect to that form.
    11. AccessDeniedHandlerImpl: Used by ExceptionTranslationFilter to handle an AccessDeniedException.
    12. FilterSecurityInterceptor: Performs security handling of HTTP resources via a filter implementation.
    13. TokenBasedRememberMeServices: Identifies previously remembered users by a Base-64 encoded cookie.
    14. DaoAuthenticationProvider: An AuthenticationProvider implementation that retrieves user details from an UserDetailsService.
    15. InMemoryDaoImpl: Retrieves user details from an in-memory list created by the bean context.

Wednesday, December 27, 2006

Data Access with Spring and JPA

The JDBC abstraction layer of Spring framework offers an understandable exception hierarchy, simplifies error handling, and greatly reduces the amount of code you'll need to write. Spring 2.0 has support for using JPA in the Data Access Layer. In this post, I will describe a step-by-step approach to implementing a Web Application that uses Spring 2.0 and Java Persistence API for Data Access. The example is the same one that I used in the previous persistence examples. This example is implemented using Spring 2.0 on Glassfish.
  1. The Entity Class: The Entity class is the Employee class shown below:
    package beans;

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;

    @Entity
    @Table(name = "EMP")
    public class Employee {

    private long empId;

    private String empName;

    private String empJob;

    private long empSal;

    @Id
    @Column(name = "EMPNO")
    public long getEmpId() {
    return empId;
    }

    public void setEmpId(long empId) {
    this.empId = empId;
    }

    @Column(name = "JOB")
    public String getEmpJob() {
    return empJob;
    }

    public void setEmpJob(String empJob) {
    this.empJob = empJob;
    }

    @Column(name = "ENAME")
    public String getEmpName() {
    return empName;
    }

    public void setEmpName(String empName) {
    this.empName = empName;
    }

    @Column(name = "EMPSAL")
    public long getEmpSal() {
    return empSal;
    }

    public void setEmpSal(long empSal) {
    this.empSal = empSal;
    }
    }
    Employee.java
  2. The JSP page: The JSP page is also the same as used previously and is shown below.
    <jsp:root version="1.2" xmlns:jsp="http://java.sun.com/JSP/Page"
    xmlns:c="urn:jsptld:http://java.sun.com/jsp/jstl/core">
    <jsp:directive.page contentType="text/html; charset=UTF-8" />
    <jsp:directive.page
    import="org.springframework.web.context.support.XmlWebApplicationContext,org.springframework.beans.BeanUtils,org.springframework.web.context.ConfigurableWebApplicationContext, org.springframework.beans.factory.BeanFactory, data.DAO" />
    <link rel="stylesheet" type="text/css" href="css/screen.css" />
    <jsp:scriptlet>
    int pageNumber=1;
    if(request.getParameter("page") != null) {
    session.setAttribute("page", request.getParameter("page"));
    pageNumber = Integer.parseInt(request.getParameter("page"));
    } else {
    session.setAttribute("page", "1");
    }
    String nextPage = (pageNumber +1) + "";
    ConfigurableWebApplicationContext wac =
    (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(XmlWebApplicationContext.class);
    wac.setServletContext(this.getServletContext());
    wac.refresh();
    session.setAttribute( "EmpList", ((DAO)wac.getBean("dao")).getData(pageNumber));
    System.out.println(((java.util.List)session.getAttribute("EmpList")).size());
    String myUrl = "pagingEmp.jsp?page=" + nextPage;
    System.out.println(myUrl);

    pageContext.setAttribute("myUrl", myUrl);
    </jsp:scriptlet>
    <h2 align="center">Emp Table with Display tag</h2>
    <jsp:useBean id="EmpList" scope="session" type="java.util.List"></jsp:useBean>
    <table>
    <tr>
    <th>Employee Id</th>
    <th>Name</th>
    <th>Job</th>
    <th>Salary</th>
    </tr>
    <c:forEach items="${EmpList}" var="emp" begin="0" end="10">
    <tr>
    <td><c:out value="${emp.empId}"></c:out></td>
    <td><c:out value="${emp.empName}"></c:out></td>
    <td><c:out value="${emp.empJob}"></c:out></td>
    <td><c:out value="${emp.empSal}"></c:out></td>
    </tr>
    </c:forEach>

    <tr>
    <td colspan="2"></td>
    <td colspan="2"><a href="${pageScope.myUrl}">nextPage</a></td>
    </tr>
    </table>
    </jsp:root>
    pagingEmp.jsp
  3. The Application Context: The application context is shown below:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value ="oracle.jdbc.driver.OracleDriver" />
    <property name="url" value="jdbc:oracle:thin:@localhost:1521/orcl" />
    <property name="username" value="scott" />
    <property name="password" value="tiger" />
    </bean>
    <bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="myPersistenceUnit" />

    <property name="dataSource" ref="dataSource" />
    <property name="loadTimeWeaver">
    <bean class="org.springframework.instrument.classloading.glassfish.GlassFishLoadTimeWeaver"/>
    </property>
    <property name="jpaDialect">
    <bean class="org.springframework.orm.jpa.vendor.TopLinkJpaDialect" />
    </property>
    <property name="jpaVendorAdapter">
    <bean class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
    <property name="showSql" value="true" />
    <property name="generateDdl" value="false" />
    <property name="databasePlatform" value="oracle.toplink.essentials.platform.database.oracle.OraclePlatform" />
    </bean>
    </property>
    </bean>

    <bean id="dao" class="data.DAO">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    </beans>
    WEB-INF/applicationContext.xml
  4. The Data Access Object: The data access object extends the JpaDaoSupport. JpaDaoSupport like JdbcTemplate implements most of the boiler-plate code for implementing JPA data access.
    package data;

    import java.util.List;

    import org.springframework.orm.jpa.JpaTemplate;
    import org.springframework.orm.jpa.support.JpaDaoSupport;

    public class DAO extends JpaDaoSupport {
    public long empId;
    public String empName;
    public String empJob;
    public long empSal;

    public List getData(long minSal) {
    JpaTemplate daoTmplt = getJpaTemplate();
    System.out.println("Creating query.");
    List result = null;
    try {
    result = daoTmplt.find("select e from Employee e");
    }catch(Throwable e) {
    e.printStackTrace();
    }
    return result;
    }
    }
    DAO.java
  5. The persistence xml: The persistence XML file does not have any persistence description as used in the JPA post. This is because it is defined in the application context XML file.
    <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
    <persistence-unit name="myPersistenceUnit" transaction-type="RESOURCE_LOCAL"></persistence-unit>
    </persistence>
    src/META-INF/persistence.xml
  6. The Web Deployment Descritor: The web deployment descriptor is shown below. Note the listener definition for org.springframework.web.context.ContextLoaderListener.
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>SpringJpa</display-name>
    <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/log4j.xml</param-value>
    </context-param>
    <listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
    </web-app>
    web.xml
  7. Setup: In order to run the example on Glassfish, you have to create an EAR and install the EAR instead of trying to deploy a WAR file on Glassfish. Deploying WAR files gives some classloading related exceptions. The reason is, as yet, unknown to me. Hope to find out soon.

Thursday, December 21, 2006

Message Driven Bean in Java EE 5

In the past, I posted a few examples of implementing Messaging using J2EE and Spring. In this post, I will give an example of how to implement Message Driven beans using Java EE 5. I used Eclipse 3.2 and Glassfish for this example. Follow these steps to run the example:
  1. Download and Install Glassfish: You can download the latest build of Glassfish from the Glassfish Download site. To install follow these steps
    1. In the download directory, run the following command
      java -Xmx256m -jar glassfish-installer-version-build.jar
    2. The previous command will create a directory by the name glassfish. Go to the glassfish directory and run this command
      ant -f setup-cluster.xml
    3. The admin console for the default installation will be at http://localhost:4848/asadmin, and the default username and password are "admin" and "adminadmin" respectively.
  2. Download and Install the Glassfish Plugin for Eclipse from here.
  3. Create a Glassfish Server in Eclipse: (For some reason, Eclipse did not detect the Server Runtime without creating a Server, we'll worry about that later)
  4. Creating the EJB 3 Message Driven Bean:
    1. Create a "Java project" in Eclipse.
    2. Add the Glassfish runtime library as a dependency for the project.
    3. The following is the code for the Message Driven Bean that I used for the Example. This is in the jms package of the Java project.
      package jms;

      import javax.annotation.Resource;
      import javax.ejb.MessageDriven;
      import javax.ejb.MessageDrivenContext;
      import javax.jms.JMSException;
      import javax.jms.Message;
      import javax.jms.MessageListener;
      import javax.jms.TextMessage;

      @MessageDriven(mappedName = "jms/testQueue")
      public class Messaging3Mdb implements MessageListener {

      @Resource
      private MessageDrivenContext mdc;

      public Messaging3Mdb() {
      }
      public void onMessage(Message inMessage) {
      TextMessage msg = null;
      try {
      msg = (TextMessage) inMessage;
      System.out.println("Message received : " + msg.getText());
      } catch (JMSException e) {
      e.printStackTrace();
      mdc.setRollbackOnly();
      }
      }
      }
      Messaging3Mdb.java
  5. Creating the Client: I used a Servlet for the client, so that I could also use JMS resource injection. To create the Client
    1. Create a "Dynamic Web Project" in Eclipse.
    2. Change the Web.xml file to Reflect Java EE 5 descriptor, as shown below
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      <display-name>Messaging3Web</display-name>
      <servlet>
      <description></description>
      <display-name>MessagingClient</display-name>
      <servlet-name>MessagingClient</servlet-name>
      <servlet-class>servlets.MessagingClient</servlet-class>
      </servlet>
      <servlet-mapping>
      <servlet-name>MessagingClient</servlet-name>
      <url-pattern>/MessagingClient</url-pattern>
      </servlet-mapping>
      <welcome-file-list>
      <welcome-file>index.html</welcome-file>
      <welcome-file>index.htm</welcome-file>
      <welcome-file>index.jsp</welcome-file>
      <welcome-file>default.html</welcome-file>
      <welcome-file>default.htm</welcome-file>
      <welcome-file>default.jsp</welcome-file>
      </welcome-file-list>
      </web-app>
      web.xml
    3. This is the code for the Servlet that acts as a client to the MDB created above
      package servlets;

      import java.io.IOException;

      import javax.annotation.Resource;
      import javax.jms.Connection;
      import javax.jms.ConnectionFactory;
      import javax.jms.Destination;
      import javax.jms.JMSException;
      import javax.jms.MessageProducer;
      import javax.jms.Queue;
      import javax.jms.Session;
      import javax.jms.TextMessage;
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      public class MessagingClient extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

      @Resource(mappedName = "jms/testQueue")
      private Queue queue;

      @Resource(mappedName = "jms/connectionFactory")
      private ConnectionFactory jmsConnectionFactory;

      public MessagingClient() {
      super();
      }

      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

      }

      public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      Connection connection = null;
      Destination dest = (Destination) queue;
      try {
      connection = jmsConnectionFactory.createConnection();
      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

      MessageProducer producer = session.createProducer(dest);
      TextMessage message = session.createTextMessage();

      message.setText("Hello");
      response.getOutputStream().println("Sending message: " + message.getText());
      System.out.println("Sending message: " + message.getText());
      producer.send(message);

      producer.send(session.createMessage());
      } catch (JMSException e) {
      e.printStackTrace();
      } finally {
      if (connection != null) {
      try {
      connection.close();
      } catch (JMSException e) {
      }
      }
      }
      }
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // TODO Auto-generated method stub
      }
      }
      MessagingClient.java
  6. Create the JMS Connection Factory and Queue: The connection factory and the queue can be created using the admin console or from the command line. The admin console is quite easy, you just have to go to the Resources->JMS Resources->Connection Factories and Resources->JMS Resources->Destination Resources. From the command line you have to use the following two commands from the GLASSFIS_HOME/bin directory.
    asadmin create-jms-resource --user admin --restype javax.jms.Queue --property imqDestinationName=testQueue jms/testQueue
    asadmin create-jms-resource --user admin --restype javax.jms.ConnectionFactory --property imqDestinationName=connectionFactory jms/connectionFactory
  7. Deploy the MDB: Since we created a Java Project, eclipse does not allow you to install from the IDE, so you have to export the Java jar file and use the admin console to deploy. Deploy it as an "EJB Module".
  8. Deploy the Client as a Web application

Tuesday, December 19, 2006

Data Access with Java Persistence API

The Java Persistence API simplifies the entity persistence model and adds new capabilities to the Java EE platform technology, it is the standard API for the management of persistence and object/relational mapping in Java EE 5. In this post, I will give a simple example of how to use JPA from a web application. I used BEA Kodo 4.1 and Weblogic application server 10.0 techinical preview. Follow these steps to run the example
  1. Download BEA Kodo 4.1 from here. You will also need to have a license file to use Kodo. The license file can be downloaded from here. Copy the license file into your classpath.

  2. You can download the Weblogic Application Server 10 TP from BEA.
Example Code
  1. Start with a "Dynamic Web Project" in Eclipse.
  2. Create the Persistence Class (Entity): The source code for the entity class is shown below:
    package beans;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;

    @Entity
    @Table(name = "EMP")
    public class Employee {

    private long empId;

    private String empName;

    private String empJob;

    private long empSal;

    @Id
    @Column(name = "EMPNO")
    public long getEmpId() {
    return empId;
    }

    public void setEmpId(long empId) {
    this.empId = empId;
    }

    @Column(name = "JOB")
    public String getEmpJob() {
    return empJob;
    }

    public void setEmpJob(String empJob) {
    this.empJob = empJob;
    }

    @Column(name = "ENAME")
    public String getEmpName() {
    return empName;
    }

    public void setEmpName(String empName) {
    this.empName = empName;
    }

    @Column(name = "EMPSAL")
    public long getEmpSal() {
    return empSal;
    }

    public void setEmpSal(long empSal) {
    this.empSal = empSal;
    }
    }
    Employee.java
    • The persistence classes, or entities are annotated with the javax.persistence.Entity annotation.
    • It is required to have a public/protected no-arg constructor.
    • Neither Entity class nor any of it's properties are to be declared final.
    • The @Id annotation defines a particular field as a primary key.
    • The properties of the Entity class are mapped to the Columns of the database with the @Column annotation.
  3. Create the Data Access Object: The code for the Data access object is shown below
    public class DAO {
    private static int pageSize = 3;
    private EntityManagerFactory emf;

    private static DAO dao = new DAO();
    private DAO() {
    }
    public static DAO getInstance() {
    return dao;
    }

    public List getData(int pageNumber) {

    EntityManager em = null;
    try {
    System.out.println(emf);
    em = emf.createEntityManager();

    Query query = em.createQuery("SELECT e FROM Employee e");
    query = query.setFirstResult(pageSize * (pageNumber - 1));
    query.setMaxResults(pageSize);
    List results = query.getResultList();
    return results;

    } catch (Exception ex) {
    ex.printStackTrace();
    return null;
    } finally {
    em.close();
    }

    }

    public void setEmf(EntityManagerFactory emf) {
    dao.emf = emf;
    }
    }
    DAO.java
    • The DAO class uses the EntityManagerFactory injected by the ContextListener on initialization, to obtain an instance of the EntityManager which is used to create Queries.
  4. Create a Context Listener: JPA annotations can be used to inject the EntityManager and the EntityManagerFactory into the Managed objects. The persistence annotations are supported only with managed classes such as servlet, filters, listeners, etc. You cannot use annotations with regular POJOs. To that end, I have created a Context Listener, which will be injected with the and which inturn injects the EntityManagerFactoryEntityManagerFactory into the DAO class.
    public class ContextListener implements ServletContextListener {

    @PersistenceUnit(unitName="emp")
    EntityManagerFactory emf;

    public void contextDestroyed(ServletContextEvent arg0) {
    }
    public void contextInitialized(ServletContextEvent arg0) {
    // EntityManagerFactory emf = Persistence.createEntityManagerFactory ("emp");
    DAO dao = DAO.getInstance();
    System.out.println("EMF : " + emf);
    dao.setEmf(emf);
    }
    }
    ContextListener.java

    The commented out line in the ContextListener class shown below
    EntityManagerFactory emf = Persistence.createEntityManagerFactory ("emp");
    is another way to obtain an instance of the EntityManagerFactory.

  5. Update Web.xml: By default, when you create a "dynamic web project" in eclipse as of today, the web.xml file will be prepared for J2EE 1.4, you have to update it to Java EE5 (note the web-app declaration below). The application server will not inject the EntityManagerFactory into the ContextListener if the Web-App version is not set to 2.5, and you will get a NullPointerException. You also have to add the ContextListener to the web.xml file.
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
    version="2.5"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>JPATest</display-name>
    <listener>
    <listener-class>listeners.ContextListener</listener-class>
    </listener>
    <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    </web-app>
    web.xml
  6. Create the JSP file: The JSP file here is similar to the previous JSP files used for the Paging examples. The only difference being the use of the DAO.getInstance() method. This change was made to be able to inject the EntityManagerFactory into the DAO object.
    <jsp:root version="1.2" xmlns:jsp="http://java.sun.com/JSP/Page"
    xmlns:c="urn:jsptld:http://java.sun.com/jsp/jstl/core">
    <jsp:directive.page contentType="text/html; charset=UTF-8" />

    <link rel="stylesheet" type="text/css" href="css/screen.css" />
    <jsp:scriptlet>
    int pageNumber=1;
    if(request.getParameter("page") != null) {
    session.setAttribute("page", request.getParameter("page"));
    pageNumber = Integer.parseInt(request.getParameter("page"));
    } else {
    session.setAttribute("page", "1");
    }
    String nextPage = (pageNumber +1) + "";
    session.setAttribute( "EmpList", data.DAO.getInstance().getData(pageNumber));
    System.out.println(((java.util.List)session.getAttribute("EmpList")).size());
    String myUrl = "pagingEmp.jsp?page=" + nextPage;
    System.out.println(myUrl);

    pageContext.setAttribute("myUrl", myUrl);
    </jsp:scriptlet>
    <h2 align="center">Emp Table with Display tag</h2>
    <jsp:useBean id="EmpList" scope="session" type="java.util.List"></jsp:useBean>
    <table>
    <tr>
    <th>Employee Id</th>
    <th>Name</th>
    <th>Job</th>
    <th>Salary</th>
    </tr>
    <c:forEach items="${EmpList}" var="emp" begin="0" end="10">
    <tr>
    <td><c:out value="${emp.empId}"></c:out></td>
    <td><c:out value="${emp.empName}"></c:out></td>
    <td><c:out value="${emp.empJob}"></c:out></td>
    <td><c:out value="${emp.empSal}"></c:out></td>
    </tr>
    </c:forEach>

    <tr>
    <td colspan="2"></td>
    <td colspan="2"><a href="${pageScope.myUrl}">nextPage</a></td>
    </tr>
    </table>
    </jsp:root>
    pagingEmp.jsp
  7. The persistence Unit definition: A persistence unit defines a set of entity classes managed by a single EntityManager. This set of entity classes represents the data contained within a single data store.
    Persistence units are defined in the persistence.xml configuration file. The persistence.xml file is to be placed in the CLASSPATH/META-INF/ directory. Here is the persistence unit I defined in the example
    <?xml version="1.0" encoding="ISO-8859-1" ?>

    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
    version="1.0">
    <persistence-unit name="emp" transaction-type="JTA">
    <class>beans.Employee</class>
    <properties>
    <property name="kodo.ConnectionURL" value="jdbc:oracle:thin:@localhost:1521/orcl" />
    <property name="kodo.ConnectionDriverName" value="oracle.jdbc.driver.OracleDriver" />
    <property name="kodo.ConnectionUserName" value="scott" />
    <property name="kodo.ConnectionPassword" value="tiger" />
    <property name="kodo.jdbc.SynchronizeMappings" value="refresh" />
    <property name="kodo.Log" value="DefaultLevel=WARN, SQL=WARN, Runtime=INFO, Tool=INFO" />
    </properties>
    </persistence-unit>

    </persistence>
    src/META-INF/persistence.xml
  8. The Jar files: Make sure that you include the following JAR files from the KODO download
    • serp.jar
    • openjpa.jar
    • ojdbc14.jar
    • kodo.jar
    • jta-spec1_0_1.jar
    • jpa.jar
    • jdo.jar
    • commons-collections-3.2.jar
    • commons-pool-1.3.jar
    • commons-lang-2.1.jar
    • jca1.0.jar
    You will also need the jar files for JSTL etc...
Resources: This post described the implementation of JPA on Weblogic, here are a few resources that help you to implement JPA in different environments

Monday, December 18, 2006

Implementing State Pattern in Java

In the previous post, I described a little about the State design pattern and it's relation to the Strategy pattern. In this post, I will show how to implement the State Pattern in Java. The following is the UML diagram for the State Pattern. A description and sample code for the example follows:State Pattern UML
  • Context: Acts as the interface to clients. The Context object maintains an instance of a ConcreteState subclass that represents the current state. The context delegates the requests to the concrete state object that represents the current state. Typically, the context passes itself as an argument to the current state object, which changes the current state of the context.
    public class StateContext {
    private State acceptedState;
    private State requestedState;
    private State grantedState;

    private State state;

    public StateContext() {
    acceptedState = new AcceptedState();
    requestedState = new RequestedState();
    grantedState = new GrantedState();
    state = null;
    }

    public void acceptApplication() {
    this.state = acceptedState;
    }

    public void requestPermission() {
    state.requestPermission(this);
    }

    public void grantPermission() {
    state.grantPermission(this);
    }

    public String getStatus() {
    return state.getStatus();
    }

    public void setState(State state) {
    this.state = state;
    }

    public State getAcceptedState() {
    return acceptedState;
    }

    public State getGrantedState() {
    return grantedState;
    }

    public State getRequestedState() {
    return requestedState;
    }

    }
    StateContext.java
  • State: An interface for encapsulating the behavior associated with a particular state of the Context.
    public interface State {
    public void grantPermission(StateContext ctx);
    public void requestPermission(StateContext ctx);
    public String getStatus();
    }
    State.java
  • Concrete State subclasses: Define the behaviour associated each state.
    public class RequestedState implements State {
    public void grantPermission(StateContext ctx) {
    System.out.println("Granting Permission");
    ctx.setState(ctx.getGrantedState());
    }
    public void requestPermission(StateContext ctx){
    System.out.println("Permission already requested");
    }
    public String getStatus() {
    return "Requested permission";
    }
    }
    RequestedState.java
    public class AcceptedState implements State {
    public void grantPermission(StateContext ctx) {

    }
    public void requestPermission(StateContext ctx){
    System.out.println("Requesting permission");
    ctx.setState(ctx.getRequestedState());
    }

    public String getStatus() {
    return "Request Received";
    }
    }
    AcceptedState.java
    public class GrantedState implements State {
    public void grantPermission(StateContext ctx) {
    System.out.println("Invalid state");
    }
    public void requestPermission(StateContext ctx){
    System.out.println("Invalid state");
    }

    public String getStatus() {
    return "Granted";
    }
    }
    GrantedState.java
  • Client
    public class StateClient {
    public static void main(String[]args) {
    StateContext ctx = new StateContext();
    ctx.acceptApplication();
    ctx.requestPermission();
    ctx.grantPermission();
    System.out.println(ctx.getStatus());
    }
    }
    StateClient.java

The State Pattern

A class that switches between a set of states, and behaves differently based on the current state it is in, is a good candidate for the state pattern. The state pattern works by encapsulating the individual states along with the corresponding state changing logic into independent classes, thus removing/minimizing conditional logic. In Design Patterns, the authors define the State pattern as:
Allow an object to alter its behavior when its internal state changes.
The object will appear to change its class.
The utility of the state pattern will not be obvious with simple examples that have a very few states and a little conditional logic to switch between states. Such simple state change can be implemented by using state variables and a little conditional logic in each method as shown below.
public class SimpleState {

private final String ON_STATE = "on";

private final String OFF_STATE = "off";

// The current state, default is off.
private String currentState = OFF_STATE;

public String redButton() {
if (currentState.equals(ON_STATE)) {
currentState = OFF_STATE;
return "State changed to off";
} else {
return "State was not changed";
}
}

public String greenButton() {
if (currentState.equals(OFF_STATE)) {
currentState = ON_STATE;
return "State changed to on";
} else {
return "State was not changed";
}
}

public static void main(String[] args) {
SimpleState simpleState = new SimpleState();
System.out.println(simpleState.redButton());
System.out.println(simpleState.greenButton());
System.out.println(simpleState.greenButton());
System.out.println(simpleState.redButton());
System.out.println(simpleState.redButton());
System.out.println(simpleState.greenButton());
}
}
SimpleState.java
This example has only two states and a couple of functions that affect the state changes, and consequently the behaviour of the SimpleState class. Even in this trivial example, you can see that adding a new state requires you to change the two methods. Moreover, in both the methods, the conditional logic will also tend to increase. The state pattern helps in this case by
  • Remove/minimize state-changing conditional logic
  • Provide a high-level view of the state changing logic
Given the advantages, the state pattern can also complicate your design when used in trivial cases when there are a very few states and you are sure that you wont be adding new states (atleast in the near future). It is not advisable to use State pattern in cases when the state changing logic is trivial.
State Pattern and Strategy Pattern
Although the state pattern looks very much like the strategy pattern, they differ in a few important aspects
  • The State Design Pattern can be seen as a self-modifying Strategy Design Pattern.
  • A change in state of a class may affect what it does, while a change is strategy of a class only changes how it does the same job.
  • In the state pattern, the state of the context object changes over time based on the a few well-defined conditions, while the strategy of a context object is set once, and is not expected to be changed.

Friday, December 15, 2006

Java Updates

Sun released updates for Java EE SDK and Java Application Platform SDK. They can be downloaded from here. These new versions bundle JDK 6 and are fully tested with JDK 6 as well
as JDK 5. The Java Application Platform SDK includes Sun Java System Access Manager (7.1 Beta), JBI Runtime with BPEL from project Open ESB and a beta version of Portlet Container to enable development and testing of JSR 168 portlets. Developer content such as Java EE 5 samples, blueprints, tutorial and API javadocs are also included. Sun Java System Application Server (9.0 Update 1 Patch 1) based on Project Glassfish is included in the SDK. This is the only SPECjAppServer result published so far on an open-source application server. It is also the first and only SPECjAppServer result published on an application server that is certified to the Java EE 5 specification. The Java EE Tools bundle has also been refreshed to use the Java Application Platform SDK Update 2.

Thursday, December 14, 2006

Paging in JSP with Hibernate

In the past, I had a few posts on how to implement pagination using displaytag(1, 2). That solution is feasible only with small result sets, the reason being that we will have the entire result set in memory (also called cache based paging). If the result set is large, then having the entire result set in memory will not be feasible. With large result sets, you cannot afford to have them in memory. In such case, you have to fetch a chunk of data at a time (query based paging). The down side of using query based paging, is that there will be multiple calls to the database for multiple page requests. In this post, I will describe how to implement simple query based caching solution, using Hibernate and a simple JSP. Time permitting, I will soon post a hybrid of cache based and query based paging example. Here is the code for implementing simple paging using a JSP and Hibernate:
  1. Download the latest version of hibernate from hibernate.org, and include all the required jars in your classpath.
  2. Hibernate configuration
    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
    <session-factory>
    <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
    <property name="connection.url">jdbc:oracle:thin:@localhost:1521/orcl</property>
    <property name="connection.username">scott</property>
    <property name="connection.password">tiger</property>
    <property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
    <property name="hibernate.current_session_context_class">thread</property>
    <mapping resource="beans/Employee.hbm.xml" />
    </session-factory>
    </hibernate-configuration>
    hibernate.cfg.xml
  3. The Employee bean class to hold the data
    public class Employee {
    public long empId;
    public String empName;
    public String empJob;
    public long empSal;
    public long getEmpId() {
    return empId;
    }
    public void setEmpId(long empId) {
    this.empId = empId;
    }
    public String getEmpJob() {
    return empJob;
    }
    public void setEmpJob(String empJob) {
    this.empJob = empJob;
    }
    public String getEmpName() {
    return empName;
    }
    public void setEmpName(String empName) {
    this.empName = empName;
    }
    public long getEmpSal() {
    return empSal;
    }
    public void setEmpSal(long empSal) {
    this.empSal = empSal;
    }
    }
    Employee.java
  4. The Employee Mapping file: This listing of the Data Access Object uses the setMaxResults, and setFirstResult method of the Query object to extract the appropriate set of results for each page.
    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    <class name="beans.Employee" table="Emp">
    <id name="empId" column="EMPNO" type="long">
    <generator class="native"/>
    </id>
    <property name="empName" column="ENAME" />
    <property name="empJob" column="JOB" />
    <property name="empSal" column="SAL" type="long"/>
    </class>
    </hibernate-mapping>
    Employee.hbm.xml
  5. The Data Access Object
    public class DAO {
    private static int pageSize = 3;
    public static List getData(int pageNumber) {
    SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
    Session session = sessionFactory.getCurrentSession();
    List result = null;
    try {
    session.beginTransaction();
    Query query = session.createQuery("from Employee");
    query = query.setFirstResult(pageSize * (pageNumber - 1));
    query.setMaxResults(pageSize);
    result = query.list();
    session.getTransaction().commit();
    } catch (Exception e) {
    e.printStackTrace();
    }
    return result;
    }
    }
    DAO.java
  6. The JSP
    <jsp:root version="1.2" xmlns:jsp="http://java.sun.com/JSP/Page"
    xmlns:c="urn:jsptld:http://java.sun.com/jsp/jstl/core">
    <jsp:directive.page contentType="text/html; charset=UTF-8" />

    <link rel="stylesheet" type="text/css" href="css/screen.css" />
    <jsp:scriptlet>
    int pageNumber=1;
    if(request.getParameter("page") != null) {
    session.setAttribute("page", request.getParameter("page"));
    pageNumber = Integer.parseInt(request.getParameter("page"));
    } else {
    session.setAttribute("page", "1");
    }
    String nextPage = (pageNumber +1) + "";
    session.setAttribute( "EmpList", data.DAO.getData(pageNumber));
    System.out.println(((java.util.List)session.getAttribute("EmpList")).size());
    String myUrl = "pagingEmp.jsp?page=" + nextPage;
    System.out.println(myUrl);

    pageContext.setAttribute("myUrl", myUrl);
    </jsp:scriptlet>
    <h2 align="center">Emp Table with Display tag</h2>
    <jsp:useBean id="EmpList" scope="session" type="java.util.List"></jsp:useBean>
    <table>
    <tr>
    <th>Employee Id</th>
    <th>Name</th>
    <th>Job</th>
    <th>Salary</th>
    </tr>
    <c:forEach items="${EmpList}" var="emp" begin="0" end="10">
    <tr>
    <td><c:out value="${emp.empId}"></c:out></td>
    <td><c:out value="${emp.empName}"></c:out></td>
    <td><c:out value="${emp.empJob}"></c:out></td>
    <td><c:out value="${emp.empSal}"></c:out></td>
    </tr>
    </c:forEach>

    <tr>
    <td colspan="2"></td>
    <td colspan="2"><a href="${pageScope.myUrl}">nextPage</a></td>
    </tr>
    </table>
    </jsp:root>
    pagingEmp.jsp

    This JSP uses the DAO class to retrieve the Employee information from the database. The page number is passed as a parameter to the DAO. Notice that I did not implement the "previous" page, but it is similar to next. I assumed that we do not know the number of results for this example.

Tuesday, December 12, 2006

Google Web Toolkit Open sourced

Google has opensourced it's Google Web Toolkit. The project is now fully opensource under the Apache 2.0 license. The new 1.3 RC has no new features since 1.2. In addition to simple directions for compiling the source yourself, the updated site includes the often-requested development roadmap as well. Here are a few of the features of GWT:
  • Dynamic, reusable UI components: Create and Send your Widgets to other developers in a JAR file.
  • Really simple RPC: To communicate from your web application to your web server, you just need to define serializable Java classes for your request and response.
  • Browser history management: GWT lets you make your site more usable by easily adding state to the browser's back button history.
  • Real debugging: In production, your code is compiled to JavaScript, but at development time it runs in the Java virtual machine, and so you can take advantage of Java debugging, with exceptions and the advanced debugging features of IDEs like Eclipse.
  • Browser compatible Your GWT applications: Automatically support IE, Firefox, Mozilla, Safari, and Opera with no browser detection or special-casing within your code in most cases.
  • JUnit integration: GWT's direct integration with JUnit lets you unit test both in a debugger and in a browser
Here is a list of few resources to kick off with GWT

Implementing JMS with Spring: Message Driven POJO

The previous post described how to implement a JMS messaging client using Spring JMS. This post will describe how to implement the Message listener as a spring Message driven POJO. Follow these steps to implement the Message driven POJO
  1. Create the Message Driven POJO: The only requirement for the Message Driven POJO is to implement the MessageListener interface. The following listing shows the code for the MDP
    public class SpringMDP implements MessageListener {
    public void onMessage(Message message) {
    try {
    System.out.println(((TextMessage) message).getText());
    } catch (JMSException ex) {
    throw new RuntimeException(ex);
    }
    }
    }
    SpringMDP.java

  2. Create the bean definition in applicationContext.xml file.
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">
    <beans>
    <!-- this is the Message Driven POJO (MDP) -->
    <bean id="messageListener" class="jms.SpringMDP" />

    <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
    <props>
    <prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
    <prop key="java.naming.provider.url">t3://localhost:20001</prop>
    </props>
    </property>
    </bean>
    <bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiTemplate">
    <ref bean="jndiTemplate" />
    </property>
    <property name="jndiName">
    <value>jms/connectionFactory</value>
    </property>
    </bean>

    <bean id="queue" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiTemplate">
    <ref bean="jndiTemplate" />
    </property>
    <property name="jndiName">
    <value>jms/testQueue</value>
    </property>
    </bean>


    <bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="concurrentConsumers" value="5" />
    <property name="connectionFactory" ref="connectionFactory" />
    <property name="destination" ref="queue" />
    <property name="messageListener" ref="messageListener" />
    </bean>
    </beans>
    WEB-INF/applicationContext.xml

    The Message listener container handles all the required functions for making the Simple POJO a Message Driven POJO.

  3. Update Web.xml to include a listener for spring.
    <listener>  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

Implementing JMS with Spring: Messaging Client

Last week, I described how to implement JMS, using a stand-alone client and a Message Driven Bean. In this post and the next, I will describe how to implement JMS using Spring and Message Driven POJOs. This post will describe how to create a Messaging client using Spring. The next post will describe how to implement a Message driven POJO. For this I used a simple servlet that, when invoked will send a text message "hello", to a destination queue. The Message driven pojo, listening on the queue will then receive and print the message. Follow these steps to run the example
  1. Setup the JMS environment as described in the "Configuring Weblogic JMS" post
  2. Create the Messaging client: This is a simple Java class which uses the spring JmsTemplate to send a message to the queue. The JmsTemplate can be used for message production and synchronous message reception. For asynchronous reception, Spring provides a number of message listener containers that are used to create Message-Driven POJOs (MDPs).
    public class QueueSender {
    private JmsTemplate jmsTemplate;
    public void setJmsTemplate(JmsTemplate jmsTemplate) {
    this.jmsTemplate = jmsTemplate;
    }
    public void sendMesage() {
    jmsTemplate.send("jms/testQueue", new MessageCreator() {
    public Message createMessage(Session session) throws JMSException {
    return session.createTextMessage("Hello");
    }
    });
    }
    }
    QueueSender.java
  3. Configure the Bean in the applicationContext.xml file: The following is alisting of the applicationContext.xml file.
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">
    <beans>
    <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
    <props>
    <prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
    <prop key="java.naming.provider.url">t3://localhost:20001</prop>
    </props>
    </property>
    </bean>

    <bean id="queueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiTemplate">
    <ref bean="jndiTemplate" />
    </property>
    <property name="jndiName">
    <value>jms/connectionFactory</value>
    </property>
    </bean>

    <bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
    <property name="jndiTemplate">
    <ref bean="jndiTemplate" />
    </property>
    <property name="cache">
    <value>true</value>
    </property>
    </bean>

    <bean id="queueTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory">
    <ref bean="queueConnectionFactory" />
    </property>
    <property name="destinationResolver">
    <ref bean="jmsDestinationResolver" />
    </property>
    </bean>

    <bean id="jmsSender" class="jms.QueueSender">
    <property name="jmsTemplate">
    <ref bean="queueTemplate" />
    </property>

    </bean>
    </beans>
    WEB-INF/applicationContext.xml

    The JndiDestinationResolver class can be used to obtain the Queue destinations using the JNDI Name. The send method in JmsTemplate (see QueueSender), uses the JNDI name, which is used by the JndiDestinationResolver to obtain the appropriate destination.

  4. Create a servlet to invoke the Message Sender: The following servlet is used to invoke the QueueSender:
     public class QueueSenderServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext());
    QueueSender sender = (QueueSender)ctx.getBean("jmsSender");
    sender.sendMesage();
    }
    }
    QueueSenderServlet.java
  5. Update the web.xml file to add the servlet and spring application context:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>SpringJMSClientWeb</display-name>
    <servlet>
    <description></description>
    <display-name>QueueSenderServlet</display-name>
    <servlet-name>QueueSenderServlet</servlet-name>
    <servlet-class>jms.QueueSenderServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>QueueSenderServlet</servlet-name>
    <url-pattern>/QueueSenderServlet</url-pattern>
    </servlet-mapping>
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    </web-app>
    web.xml

    The listener defined web.xml (ContextLoaderListener) by default loads the applicationContext.xml file in WEB-INF directory of the web application.
In the next post, we will see how implement the Message Driven POJO to consume the message sent from here.

Monday, December 11, 2006

Java Platform Standard Edition 6

Sun Microsystems, Inc. announced the availability of Java Platform Standard Edition 6 (Java SE 6) today. In less than 2yrs of the release of Java SE 5, we have another version of Java. Hope the industry can catch up the new releases so quick. Considering the fact that IBM released the latest version of Rational developer platform today, which incorporates Java 5, it seems that Sun is going too fast. And we know that they already started working on Java SE 7 (dolphin). Here's a list of key features available in the new version.
  • Scripting Language Support: The new framework API for scripting languages allow you to
    • Access and control Java technology-based objects from a scripting environment
    • Create web content with scripting languages
    • Embed scripting environments within Java technology-based applications
  • New Security Features:The new security features include
    • Native platform Security (GSS/Kerberos) integration.
    • Java Authentication and Authorization Service (JAAS) login module that employs LDAP authentication
    • New Smart Card I/O API
  • Integrated Web Services
    • New API for XML digital signature services for secure web services
    • New Client and Core Java Architecture for XML-Web Services (JAX-WS) 2.0 APIs
    • New support for Java Architecture for XML Binding (JAXB) 2.0
For a more complete list of the features, visit the Java SE 6 website.

Rational Software Development Platform v7.0

IBM has announced the release of the Rational software delivery platform version 7.0. The platform includes the following products:Among the notable features:
  • Extends Eclipse 3.2
  • support for J2EE 1.2, 1.3, 1.4 specifications (no Java EE 5)
  • WebSphere Application Server v5.1, v6.0, v6.1: WebSphere Application Server v5.1, v6.0, v6.1. WebSphere Portal Server v5.0 and v6.0
  • Java Server Faces reference implementation, JSF components and visual tools
  • Install only the features you need through flexible, granular installation options
  • No support for Microsoft Windows Visa
For more information visit:

Implementing Strategy Pattern in Java

The previous post described the Strategy pattern in brief. I listed out where and why the strategy pattern may be used. This post describes how to implement command pattern in Java and also some implementation considerations. This example here uses sorting algorithms. Two sorting algorithms (Bubble sort and Quick sort) are implemented and the client can select either the algorithms. Here is the UML diagram for the Strategy Pattern.Strategy Pattern UMLThe following is a simple description of each of the elements of the above diagram, followed by a simple implementation.
  • Strategy: This is an interface to describe the individual algorithms.
    public interface SortInterface {
    public void sort(double[] list);
    }
    SortInterface.java
  • ConcreteStrategy: Implements Strategy Interface and contains the logic for the algorithm.
    public class QuickSort implements SortInterface {
    public void sort(double[] a) {
    quicksort(a, 0, a.length - 1);
    }
    private void quicksort(double[] a, int left, int right) {
    if (right <= left) return;
    int i = partition(a, left, right);
    quicksort(a, left, i-1);
    quicksort(a, i+1, right);
    }

    private int partition(double[] a, int left, int right) {
    int i = left;
    int j = right;
    while (true) {
    while (a[i]< a[right])
    i++;
    while (less(a[right], a[--j]))
    if (j == left) break;
    if (i >= j) break;
    exch(a, i, j);
    }
    exch(a, i, right);
    return i;
    }

    private boolean less(double x, double y) {
    return (x < y);
    }

    private void exch(double[] a, int i, int j) {
    double swap = a[i];
    a[i] = a[j];
    a[j] = swap;
    }
    }
    QuickSort.java
    public class BubbleSort implements SortInterface {
    public void sort(double[] list) {
    double temp;
    for(int i = 0; i < list.length; i++) {
    for(int j = 0; j < list.length - i; j++) {
    if(list[i] < list[j]) {
    temp = list[i];
    list[i] = list[j];
    list[j] = temp;
    }
    }
    }
    }
    }
    BubbleSort.java
  • Context: The context maintains a reference to a Strategy object and forwards client requests to the strategy. Context may also define an interface to let Strategies access context data.
    public class SortingContext {
    private SortInterface sorter = null;

    public void sortDouble(double[] list) {
    sorter.sort(list);
    }

    public SortInterface getSorter() {
    return sorter;
    }

    public void setSorter(SortInterface sorter) {
    this.sorter = sorter;
    }
    }
    SortingContext.java
  • Client: The client sets the concrete strategy in the context and invokes the context to run the algorithm. You can also have the context set the Concrete strategy implementation itself, based on the request.
    public class SortingClient {
    public class SortingClient {
    public static void main(String[] args) {
    double[] list = {1,2.4,7.9,3.2,1.2,0.2,10.2,22.5,19.6,14,12,16,17};
    SortingContext context = new SortingContext();
    context.setSorter(new BubbleSort());
    context.sortDouble(list);
    for(int i =0; i< list.length; i++) {
    System.out.println(list[i]);
    }
    }
    }
    SortingClient.java
Note: The quick sort algorithm used here is from "princeton university" site (modified a little to fit the strategy pattern).

The Strategy Pattern

The strategy pattern is intended to provide a means to define a family of algorithms, encapsulate each one as an object, and make them interchangeable. It is useful for situations where it is necessary to dynamically swap the algorithms used in an application. In Design Patterns, the authors define the Command pattern as:
Define a family of algorithms, encapsulate each one, and make them interchangeable.
Strategy lets the algorithm vary independently from clients that use it.
The Strategy pattern consists of a family of related algorithms behind a driver class called the Context. Either the client or the context select the which one of the algorithms to use for the given situation. The strategy pattern may be used in the following scenarios:
  • When you have many related classes that differ only in behavior. Strategy pattern provides a way to configure a class with one of many behaviors.
  • Strategy pattern can be used when you have different variants of an algorithm. Each variant can be encapsulated within a strategy.
  • An algorithm uses internal data structures that need not be exposed to the client.
  • A class defines many behaviors, which are selected by multiple conditional statements. Eliminate conditional statements by encapsulating each behaviour in a strategy.
Advantages of Strategy Pattern
  • Hierarchies of Strategy classes can be used to define a family of algorithms or behaviors for contexts to reuse.
  • Encapsulating the algorithm in separate Strategy classes lets you vary the algorithm independently of its context.
  • The Strategy pattern offers an alternative to conditional statements for selecting desired behavior. When different behaviors are Encapsulating different behaviours in different Strategy classes eliminates the need for conditional statements.
Drawbacks of Strategy pattern
  • A client must understand how Strategies differ to be able to select the right strategy. If possible, the context may be albe to this for you.
  • Strategy pattern increases the number of objects in an application.

Friday, December 08, 2006

PDF Generation with Big Faceless Report Generator

Big Faceless Report Generator is a commercial Java API for generating PDF files from XML input. The report generator is built on the Big Faceless Java PDF library. It has a very easy to use API, but the one thing that I like most about it is, for it is more than a bargain for the price you pay for it. It easily out performs the open source PDF generators (iText and XSL FOP) and also has a lot of intersting features.

Skip to Sample Code
  • HTML-style Tables - auto-sized nested tables with full control over padding, margins and borders
  • Support for CSS2 Style sheets
  • Create inline graphs and charts with XML, direct from the database
  • Includes a servlet and a servlet filter for simple generation of PDF's from XML or JSP pages.
  • Auto pagination of content with page headers and footers
  • Familiar HTML syntax - <a>, <ul>, <p>, <table>, <td> and so on - simpler and faster than FOP
  • Unicode support, Encryption, TrueType fonts, Barcodes and more
  • Load existing PDF documents as templates
  • Digitally sign documents
  • Create and edit interactive Forms, or "AcroForms"
The following is an example of how to use the Report generation library to create PDF files using an XML for input Data, and an XSL as a template. Follow these steps to implement the example
  1. Download Big Faceless Report generator from here. You only have to include the bforeport.jar file in your classpath.
  2. Create the input XML file as shown below:
    <?xml version="1.0" encoding="UTF-8"?>
    <Org>
    <Employee>
    <firstName>Asif</firstName>
    <lastName>Mandvi</lastName>
    <dateOfBirth>1/1/1900</dateOfBirth>
    </Employee>
    <Employee>
    <firstName>James</firstName>
    <lastName>Baker</lastName>
    <dateOfBirth>1/1/1900</dateOfBirth>
    </Employee>
    <Employee>
    <firstName>Jon</firstName>
    <lastName>Stewart</lastName>
    <dateOfBirth>1/1/1900</dateOfBirth>
    </Employee>
    <Employee>
    <firstName>Stephen</firstName>
    <lastName>Colbert</lastName>
    <dateOfBirth>1/1/1900</dateOfBirth>
    </Employee>
    <Employee>
    <firstName>Samantha</firstName>
    <lastName>Bee</lastName>
    <dateOfBirth>1/1/1900</dateOfBirth>
    </Employee>
    <Employee>
    <firstName>Jon</firstName>
    <lastName>Oliver</lastName>
    <dateOfBirth>1/1/1900</dateOfBirth>
    </Employee>
    </Org>
    test.xml
  3. Create the template for the PDF(XSL) as shown below.
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" />
    <xsl:preserve-space elements="true" />
    <xsl:template match="Org">
    <pdf>
    <body>
    <table font-size="12pt" width="700px">
    <tr font-weight="bold">
    <td>First Name</td>
    <td>Last Name</td>
    <td>Date of Birth</td>
    </tr>
    <xsl:for-each select="/Org/Employee">
    <tr>
    <td>
    <xsl:value-of select="firstName" />
    </td>
    <td>
    <xsl:value-of select="lastName" />
    </td>
    <td>
    <xsl:value-of select="dateOfBirth" />
    </td>
    </tr>
    </xsl:for-each>
    </table>
    </body>
    </pdf>
    </xsl:template>
    </xsl:stylesheet>
    test.xsl
    This XSL file will be used to create the final XML file that will sent as input to the Report generator.
  4. Transform the XML to the format required by the report generator: The XML file cannot be used as input to the report generator directly. It has to be first transformed into the required format. That is reason for using the XSL.
    public class ConvertXML {
    public void renderReport() {
    try {
    TransformerFactory factory = TransformerFactory.newInstance();
    StreamSource stylesheet = new StreamSource(new FileInputStream("c:\\pdf\\test.xsl"));
    Transformer transformer = factory.newTransformer(stylesheet);
    Source src = new StreamSource(new FileInputStream("c:\\pdf\\test.xml"));
    Result res = new StreamResult(new FileOutputStream("c:\\pdf\\intermediate.xml"));
    transformer.transform(src, res);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
    ConvertXML.java
  5. The following code can be used to generate the final PDF: The PDFGenerator first uses the ConvertXML to transform the input to the report generator input format (intermediate.xml), and then invokes the report generator.
    public class PDFGenerator {
    public void createPDF(String xmlfile, OutputStream out) {
    ReportParser parser;
    try {
    parser = ReportParser.getInstance();
    InputSource src = new InputSource(new FileInputStream(xmlfile));
    PDF pdf = (PDF) parser.parse(src);
    pdf.render(out);
    out.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    public static void main(String args[]) {
    PDFGenerator gen = new PDFGenerator();
    OutputStream os = null;
    try {
    ConvertXML cx = new ConvertXML();
    cx.renderReport();
    os = new FileOutputStream("c:\\pdf\\test.pdf");
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }
    gen.createPDF("C:\\pdf\\intermediate.xml", os);
    }
    }
    PDFGenerator.java

Thursday, December 07, 2006

Basic web service implementation

This post describes how to implement a simple webservice using Weblogic, Eclipse, and Apache Axis. We will go through these steps to implement the Webservice
  1. Enable Weblogic domain for WebServices
  2. Create a simple web service class.
  3. Auto-generate WebServices classes in Eclipse
  4. Auto-generate the classes for calling the web service.
  5. Create a Client Application
  1. Enable Weblogic domain for WebServices: Follow these steps to enable your weblogic domain for web services.
    1. Start the Configuration Wizard (c:/bea9.2/weblogic92/common/bin/config.cmd)
    2. In the Welcome window, select Extend an Existing WebLogic Domain. Click Next.
    3. Select the domain to which you want to apply the extension template. Click Next.
    4. Select Extend My Domain Using an Existing Extension template.
    5. Enter the following value in the Template Location text box: WL_HOME/common/templates/applications/wls_webservice.jar. Click Next.
    6. Select no. Click next.
    7. Verify that you are extending the correct domain, then click Extend.
  2. Create a simple web service class: Create an Eclipse Web Project. The reason for using a Web Project is that the J2EE specification requires that for implementing you need one of the following.
    • A Java class running in the Web container.
    • A stateless session EJB running in the EJB container.
    Create the following class within the web application.
    public class TestService {
    public String sayHello(String message) {
    System.out.println("sayHello:" + message);
    return "You said '" + message + "'";
    }
    }
    TestService.java
  3. Auto-generate WebServices classes in Eclipse: Right-click on the TestService.java class and select Web Services->Create Web Service. If you have a weblogic server defined in eclipse, then the Web service will be automatically published to the server. Make sure that your server definition looks like this.

  4. Auto-generate the classes for calling the web service: Create a Java application and copy the generated WSDL file from the web project. Right-click on the WSDL file and Web Services->Generate client. All the required classes will be generated, and the jar files will also be imported.
  5. Create a Client Application: We will use a simple Java client for this web service. The following is the code for the client application.
    import java.rmi.RemoteException;
    import service.TestService;
    import service.TestServiceProxy;
    public class SimpleClient {
    public static void main(String[] args) {
    TestService service = new TestServiceProxy();
    try {
    System.out.println(service.sayHello("Hello"));
    } catch (RemoteException e) {
    e.printStackTrace();
    }
    }
    }
This example was run on Weblogic 9.2, Eclipse Callisto 3.2, Java 5.0.

Wednesday, December 06, 2006

Messaging Quickstart: Sample Code

The previous post described how to setup a Queue in Weblogic Server. This post shows the code necessary to run a Simple Messaging example using a servlet and Message Driven Bean. You can always implement an message listener instead of using a Message Driven Bean, but using MDBs is much cleaner and easier. Follow these steps to run the example
  1. Setup XDoclet
    1. Download XDoclet from here, and extract it.
    2. In Eclipse->Window->preferences, select xdoclet and set the Xdoclet home to the appropriate directory.
  2. Create the Message Driven Bean
    1. Create an EJB project in Eclipse.
    2. In the J2EE perspective, right-click on the Deployment descriptor and create a new Message Driven Bean. Eclipse generates the required classes and the ejb-jar.xml file with the new MDB definition in it. Modify the Bean to look like this
      public class MessagingExampleBean implements javax.ejb.MessageDrivenBean, javax.jms.MessageListener {
      private javax.ejb.MessageDrivenContext messageContext = null;
      public void setMessageDrivenContext(javax.ejb.MessageDrivenContext messageContext) throws javax.ejb.EJBException {
      this.messageContext = messageContext;
      }
      public void ejbCreate() {
      }
      public void ejbRemove() {
      messageContext = null;
      }
      public MessagingExampleBean() {
      }
      public void onMessage(javax.jms.Message message) {
      System.out.println("Message Driven Bean got message " + message);
      }
      }
      Add the following definitions to the ejb-jar.xml
      <?xml version="1.0" encoding="UTF-8"?>
      <ejb-jar version="2.1" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">
      <display-name>MessagingExample</display-name>
      <enterprise-beans>
      <message-driven>
      <display-name>MessagingExampleMDB</display-name>
      <ejb-name>MessagingExampleMDB</ejb-name>
      <ejb-class>jms.MessagingExampleMdb</ejb-class>
      <transaction-type>Bean</transaction-type>
      <message-destination-type>javax.jms.Queue</message-destination-type>
      </message-driven>
      </enterprise-beans>
      <assembly-descriptor>
      <container-transaction>
      <method>
      <ejb-name>MessagingExampleMDB</ejb-name>
      <method-name>*</method-name>
      </method>
      <trans-attribute>Required</trans-attribute>
      </container-transaction>
      </assembly-descriptor>
      </ejb-jar>
    3. Create a new file weblogic-ejb-jar.xml. This is required for Weblogic bindings.
      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE weblogic-ejb-jar PUBLIC "-//BEA Systems, Inc.//DTD WebLogic 8.1.0 EJB//EN" "http://www.bea.com/servers/wls810/dtd/weblogic-ejb-jar.dtd">
      <weblogic-ejb-jar>
      <weblogic-enterprise-bean>
      <ejb-name>MessagingExampleMDB</ejb-name>
      <message-driven-descriptor>
      <pool>
      <max-beans-in-free-pool>5</max-beans-in-free-pool>
      <initial-beans-in-free-pool>5</initial-beans-in-free-pool>
      </pool>
      <destination-jndi-name>jms/testQueue</destination-jndi-name>
      <initial-context-factory>weblogic.jndi.WLInitialContextFactory</initial-context-factory>
      <connection-factory-jndi-name>jms/connectionFactory</connection-factory-jndi-name>
      <jms-polling-interval-seconds>20</jms-polling-interval-seconds>
      </message-driven-descriptor>
      <transaction-descriptor>
      <trans-timeout-seconds>3600</trans-timeout-seconds>
      </transaction-descriptor>

      </weblogic-enterprise-bean>
      </weblogic-ejb-jar>
  3. Create the Client. For this example, I used a servlet that simply sends a "Hello" message to the MDB through the Queue. Here is the code for it
    public class MessaginClientServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
    public final static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";
    public final static String JMS_FACTORY = "weblogic.examples.jms.QueueConnectionFactory";
    public final static String QUEUE = "weblogic.examples.jms.exampleQueue";
    public MessaginClientServlet() {
    super();
    }
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
    Context ctx = getInitialContext("t3://localhost:20001");
    QueueConnectionFactory qconFactory;
    QueueConnection connection;
    QueueSession session;
    QueueSender sender;
    Queue queue;
    TextMessage msg;

    qconFactory = (QueueConnectionFactory) ctx.lookup("jms/connectionFactory");
    connection = qconFactory.createQueueConnection();
    session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    queue = (Queue) ctx.lookup("jms/testQueue");
    msg = session.createTextMessage();
    sender = session.createSender(queue);
    msg.setText("Hello World");
    connection.start();
    sender.send(msg);
    session.close();
    connection.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    private InitialContext getInitialContext(String url) throws NamingException {
    Hashtable<String, String> env = new Hashtable<String, String>();
    env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
    env.put(Context.PROVIDER_URL, url);
    return new InitialContext(env);
    }
    }

Popular Posts