Про то как создать и развернуть на сервере приложений JBoss простой message driven bean используя аннотации спецификации EJB3. Страница 4

Сервлет

Остановимся подробнее на сервлете.

 package mdbtest.web;

 import java.io.IOException;
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.Properties;
 import javax.jms.Queue;
 import javax.jms.QueueConnection;
 import javax.jms.QueueConnectionFactory;
 import javax.jms.QueueSender;
 import javax.jms.QueueSession;
 import javax.jms.TextMessage;
 import javax.naming.Context;
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.PersistenceUnit;
 import javax.servlet.ServletException;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;  
 import javax.sql.DataSource;

 public class SimpleServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

  private static final long serialVersionUID = 1L;

  @PersistenceUnit
  EntityManagerFactory emf;

  public void init() throws ServletException {}

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

   // set the MIME type of the response, "text/html"
   response.setContentType("text/html");
   ServletOutputStream out = response.getOutputStream();

   // Begin assembling the HTML content
   out.println("<html><head></head><body><h1>I'am SimpleServlet.</h1>");

   Properties properties = new Properties();
   properties.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
   properties.put("java.naming.factory.url.pkgs", "=org.jboss.naming:org.jnp.interfaces");
   properties.put("java.naming.provider.url", "localhost:1099");
   try {
    Context context = new InitialContext(properties);
    Queue queue = (Queue) context.lookup("queue/mdbAlexTest");
    QueueConnectionFactory factory = (QueueConnectionFactory) context.lookup("ConnectionFactory");
    QueueConnection cnn = factory.createQueueConnection();
    QueueSession sess = cnn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
    TextMessage msg = sess.createTextMessage();
    long sent = System.currentTimeMillis();
    msg.setLongProperty("sent", sent);

    QueueSender sender = sess.createSender(queue);
    // посылаем сообщения
    for (int i = 0; i < 12; i++) {
     msg.setText("This is " + (i + 1) + " message to SimpleMessageBean");
     System.out.println("Sending message: " + msg.getText());
     sender.send(msg);
    }
    sess.close();
   } catch (Exception e) {
    e.printStackTrace();
   }

   Connection cn = null;
   try {
    Context ctx = new InitialContext();
    DataSource datasource = (DataSource) ctx.lookup("java:/MySqlDS");
    cn = datasource.getConnection();
   } catch (NamingException e) {
    e.printStackTrace();
   } catch (SQLException e) {
    e.printStackTrace();
   }
   Statement st;
   // читаем из базы данных
   try {
    st = cn.createStatement();
    ResultSet rs = st.executeQuery("select * from message_table");
    if (rs.next()) {
     do {
      out.println("<h2>" + rs.getString("message") + "</h2>");
     } while (rs.next());
    }
    rs.close();
    cn.close();
   } catch (SQLException e) {
    e.printStackTrace();
   }
   out.println("</body></html>");
  }
 }

Ограничения сервера приложений JBoss 4.2 в использовании аннотаций Dependency injection

К сожалению нам не удастся насладиться использованием аннотаций в данной реализации сервера приложений JBoss. Со слезами на глазах читали мы эти строки:

@EJB annotations are usable in servlets and JSPs, but unfortunately, we have not yet updated tomcat to support it. Also, Tomcat works with the old XML format so you cannot use XML either. So for now, you must lookup the EJB via its global JNDI name. This is not compliant, but if you abstract out enough you'll be fine.

The @PersistenceUnit and elements can be used within Servlets and JSPs to access EntityManagerFactory only. You cannot inject EntityManagers directly into web components. Unfortunately, again, Tomcat doesn't support them, so you have to lookup the EntityManagerFactory in JNDI. To be able to do that you need to set the entity.manager.factory.jndi.name property in your persistence.xml file.

Нет, использовать старые XML дескрипторы - не наш метод. Остается надеяться что в пятой версии JBoss все будет хорошо и слезы высохнут..

Ant скрипт для сборки EAR файла и развертывания приложения на сервере

Продолжим после сентиментального перерыва. Нам осталось пересмотреть Ant скрип для развертывания нашего тестового приложения.

Собственно мы его почти полностью переписали.

 <?xml version="1.0" encoding="ISO-8859-1"?>
 <project name="MDBTest" basedir="." default="generate-ear">

  <property file="build.properties" />

  <path id="base.path">
   <fileset dir="${project.libs}">
    <include name="**/*.jar" />
   </fileset>
  </path>

  <target name="undeploy" description="Undeploy EAR from server">
   <delete file="${deploy.dir}/${ear.file}" />
  </target>

  <target name="generate-ear" depends="undeploy, generate-ear-jar, generate-ear-war">
   <echo message="Creating ear" />

   <!-- 1. copy application.xml -->
   <copy todir="${classes.dir}/META-INF">
   <fileset dir="META-INF" includes="**/*.xml"/>
   </copy>  

   <!-- 2. generate module -->
   <antcall target="generate-jar">
    <param name="jarfile" value="${deploy.dir}/${ear.file}"/>
    <param name="jarbasedir" value="${classes.dir}"/>
    <param name="jarincludes" value="**/*.*"/>
   </antcall>

  </target>  

  <target name="generate-ear-jar">  

   <echo message="Creating jar" />

   <!-- 1. create temp dir -->
   <mkdir dir="${classes.dir}/temp-jar" />

   <!-- 2. copy class files -->
   <copy todir="${classes.dir}/temp-jar">
    <fileset dir="${build.dir}" includes="**/mdbtest/**/*.class" excludes="**/web/**/*.class" />
   </copy>  
   <!-- 3. copy persistence.xml -->
   <copy todir="${classes.dir}/temp-jar/META-INF">
    <fileset dir="${src.dir}/META-INF" includes="**/*.xml"/>
   </copy>  

   <!-- 4. generate module -->
   <antcall target="generate-jar">
    <param name="jarfile" value="${classes.dir}/MDBTest.jar"/>
    <param name="jarbasedir" value="${classes.dir}/temp-jar"/>
    <param name="jarincludes" value="**/*.*"/>
   </antcall>

   <!-- 5. delete temp dir  -->
   <delete dir="${classes.dir}/temp-jar" />

  </target>

  <target name="generate-ear-war">

   <echo message="Creating war" />

   <!-- 1. create temp dir -->
   <mkdir dir="${classes.dir}/temp-war" />

   <!-- 2. copy class files -->
   <copy todir="${classes.dir}/temp-war/WEB-INF/classes">
    <!--<fileset dir="bin/mdbtest/web" includes="*.class" />-->
    <fileset dir="${build.dir}" includes="**/mdbtest/web/*.class" />        
   </copy>    

   <!-- 3. copy web.xml -->
   <copy todir="${classes.dir}/temp-war/WEB-INF">
    <fileset dir="WEB-INF" includes="**/*.xml"/>
   </copy>  

   <!-- 4. generate module -->
   <antcall target="generate-jar">
    <param name="jarfile" value="${classes.dir}/mdbtestweb.war"/>
    <param name="jarbasedir" value="${classes.dir}/temp-war"/>
    <param name="jarincludes" value="**/*.*"/>
   </antcall>  

   <!-- 5. delete temp dir  -->
   <delete dir="${classes.dir}/temp-war" />    
  </target>

  <target name="generate-jar">
   <delete file="${jarfile}"/>
   <jar jarfile="${jarfile}" basedir="${jarbasedir}" includes="${jarincludes}"/>
  </target>  

 </project>

И не забудем добавить в последнюю строчку в build.properties:

ear.file=MDBTest.ear

Готово. Запускаем Ant скрипт и, если все прошло удачно, у нас получится архив с приложением. EAR попадет сразу в JBoss, будет на лету развернут и готов к работе. Нам останется набрать в браузере адрес сервлета и посмотреть результаты работы всего приложения.

Примерно вот так: http://localhost:8080/mdbtestweb/SimpleServlet

Файлы, используемые в статье

Страница:

Александр Смелков
Санкт-Петербург Лето 2007