Version 4

    Chinese Version:

    开发基于JBoss AS 7.2.0的Java EE程序 - 03.如何创建EJB、WAR、Connector和EAR工程 or 开发基于JBoss AS 7.2.0的Java EE程序 - 03.如何创建EJB、WAR、Connector和EAR工程

     

    Summary

     

    This article describes how to create Java EE application(EJB, WAR, Connector and EAR) based on JBoss AS 7.2.0.

    IDE: Eclipse.

     

    1. Create Enterprise Application Project

     

    Please refer to JBoss AS 7.2.0 - Java EE application development - 01.How to set up development environment to set up your IDE.

     

    1.1 Create an 'Server' in Eclipse.

     

    Open your eclipse, find the "Servers" view and do as bellow demonstration:

              

     

     

              

     

              

     

              

          

     

               Push above "Finish" button, a "JBoss AS Server" is created and you can start it:

              

     

              The log:

     

                Now, let's stop it:

     

     

     

    1.2 Create Enterprise Application Project

    Select the menu "File" > "New" > "Project ...", and select "Java EE > Enterprise Application Project" in the next dialog, like this:

            

     

             Next, input project name(here: "ybxiang-forum"):

            

     

           Next!

     

           Please do NOT forget to check the box “Generate application deployment descriptor”:

           

     

           

     

          We can changed the generated modules names:

          

     

           Finish!

     

           Result:

          

     

          

     

          If your codes contains Chinese, Japanese ... Characters, then you had better to set UTF-8 encoding:

     

     

    Let's change <context-root>ybxiang-forum-war</context-root> to <context-root>/</context-root> in application.xml.

     

     

    2. add capabilities to WAR application(here: ybxiang-forum-war)

    2.1 add JSF capability

     

     

     

    Result review

    (a) web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
      <display-name>ybxiang-forum-war</display-name>
      <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
      </servlet-mapping>
    </web-app>

    (b) faces-config.xml

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

     

    <faces-config
        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-facesconfig_2_1.xsd"
        version="2.1">

     

    </faces-config>

     

    Let's remove <display-name> element from web.xml(you can keep this element too, it is NOT very useful) and add new lines which are marked blue as bellow:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="3.0" 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_3_0.xsd">
        <context-param>
          <param-name>PARAMETER_ENCODING</param-name>
          <param-value>UTF-8</param-value>
        </context-param>
        <context-param>
            <param-name>javax.faces.PROJECT_STAGE</param-name>
            <param-value>Development</param-value>
        </context-param>

        <context-param>
            <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
            <!-- do NOT use 'server' value, because it will cause javax.faces.application.ViewExpiredException -->
            <param-value>client</param-value>
        </context-param>

        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>/faces/*</url-pattern>
        </servlet-mapping>
        <session-config>
            <session-timeout>600</session-timeout>
        </session-config>
        <welcome-file-list>
            <welcome-file>faces/index.xhtml</welcome-file>
        </welcome-file-list>

    </web-app>

     

    Where

    • PARAMETER_ENCODING:parameters(in html form?) encoding.
    • javax.faces.STATE_SAVING_METHOD: session state info. is saved in client (web browser) side.

     

     

     

    2.2 template.xhtml

     

    Let's create a new template file to display most pages in same style.

     

    (a) template/template.xhtml

    <?xml version='1.0' encoding='UTF-8' ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:ui="http://java.sun.com/jsf/facelets">
        <h:head>
                <title>
                    <ui:insert name="title"/>
                    <h:outputText value=" - http://javaarm.com" />
                </title>
                <link rel="shortcut icon" href="#{request.contextPath}/img/favicon.ico"/>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                <link rel="stylesheet" type="text/css" media="all" href="#{request.contextPath}/css/template.css" />
                <ui:insert name="headMetaData"/>
        </h:head>
        <!-- make the whole body in center -->
        <style type="text/css">
            <!--
            body{ margin:0 auto;}
            -->
        </style>
        <h:body style="width:1000px;" styleClass="yui-skin-sam" >
            <a name="header" id="header" />
            <ui:include src="/template/navigator.xhtml" />
            <hr class="separator" />
            <f:view>
                <h:messages id="messages" globalOnly="true" styleClass="message"
                    errorClass="errormsg" infoClass="infomsg" warnClass="warnmsg"
                    rendered="#{showGlobalMessages != 'false'}"/>
                <ui:insert name="body" />
            </f:view>
            <hr class="separator" />
            <a name="footer" id="footer" />     
            <h:outputLink value="#{request.contextPath}/faces/index.xhtml" ><h:outputText value="Home" /></h:outputLink>
            <h:outputText value="  " />
            <h:outputLink rendered="#{not forPrint}" value="#header"><h:outputText value="Header" /></h:outputLink>
            <hr class="separator" />
            <ui:include src="/template/footer.xhtml" />
        </h:body>
    </html>

     

     

    (b) template/navigator.xhtml

     

    This is a navigator component.

     

    <?xml version='1.0' encoding='UTF-8' ?>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

     

    <ui:composition xmlns="http://www.w3.org/1999/xhtml"

        xmlns:ui="http://java.sun.com/jsf/facelets"

        xmlns:h="http://java.sun.com/jsf/html">

        <div>

            <h:form id="search" >

                <table width="100%" border="0" cellpadding="0" cellspacing="0" >

                    <tr>

                        <td width="50%">

                            <h:outputLink value="#{request.contextPath}/faces/index.xhtml" >

                                <h:outputText value="Home" />

                            </h:outputLink>

                        </td>

                        <td width="50%" style="text-align: right;" >

                        </td>

                    </tr>

                    <tr>

                        <td colspan="100">

                            <h:graphicImage value="#{request.contextPath}/img/biggrin.gif" style="border:0px;" />

                            <h:outputText value=" " />

                        </td>

                    </tr>

                </table>

            </h:form>

        </div>   

    </ui:composition>

     

     

     

    (c) template/footer.xhtml

    <?xml version='1.0' encoding='UTF-8' ?>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <ui:composition xmlns="http://www.w3.org/1999/xhtml"

        xmlns:ui="http://java.sun.com/jsf/facelets"

        xmlns:h="http://java.sun.com/jsf/html"

        xmlns:f="http://java.sun.com/jsf/core">

        <div style="margin-top: 2px; text-align: center">

            <h:outputText value="www.jdetail.com" />

        </div>   

    </ui:composition>

     

    (d) css/template.css

    .separator{
        border:0px; border-top: 1px dashed #6293bb;
    }
    .topic_separator{
        text-decoration: none;background: #ffffff
    }
    .linelessLink{
        text-decoration: none;
    }
    .message li {
        background: no-repeat left center;
        padding-top: 1px;
        padding-left: 20px;
        margin-left: 3px;
    }
    .message li.infomsg {
        background-image: url(../img/msginfo.png);
    }
    .message li.errormsg {
        background-image: url(../img/msgerror.png);
    }
    .message li.warnmsg {
        background-image: url(../img/msgwarn.png);
    }

     

    (e) index.xhtml

    Let's create a index.xhtml to test our codes.

     

    <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <ui:composition xmlns="http://www.w3.org/1999/xhtml"

                    xmlns:ui="http://java.sun.com/jsf/facelets"

                    xmlns:f="http://java.sun.com/jsf/core"

                    xmlns:h="http://java.sun.com/jsf/html"
                   template="/template/template.xhtml">

     

       <ui:define name="title">

            <h:outputText value="JAVA and ARM research" />

        </ui:define>

     

       <ui:define name="headMetaData">

            <!-- 'head' module is used to include css/script files, do NOT display anything in it. -->

            <link rel="stylesheet" type="text/css" media="all" href="#{request.contextPath}/css/index.css" />

        </ui:define>

     

       <ui:define name="body">

            <div>

                <div class="div-domain"><h:outputText value="Administration" /></div>

            </div>

        </ui:define>

    </ui:composition>

     

     

     

    2.4Test

     

           

     

     

         

     

         

     

    Result:

     

     

    3. add capabilities to EJB (here: ybxiang-forum-ejb)

    3.1 add JPA capability to our EJB module

              

     

     

     

     

     

     

     

     

     

     

     

     

     

    Result:

     

    Now, let's modify persistence.xml as bellow:

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

    <persistence version="2.1"

        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_2_1.xsd">

     

        <persistence-unit name="ybxiang-forum-persistence-unit">

            <jta-data-source>java:jboss/datasources/ybxiangForumMySqlDataSource</jta-data-source>

            <properties>

                <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>

                <property name="hibernate.hbm2ddl.auto" value="update"/>

                <property name="hibernate.show_sql" value="false"/>

                <property name="hibernate.format_sql" value="true"/>

            </properties>

        </persistence-unit>

    </persistence>

     

     

     

    3.2 Data source configuration

     

    We have finished it in JBoss AS 7.2.0 - Java EE application development - 02.How to configure MySql Data source

    NOTE: datasource name in 3.1 ("ybxiangForumMySqlDataSource" ) must match the one configured in JBoss AS 7.2.0 - Java EE application development - 02.How to configure MySql Data source

     

    3.3 Test

     

    Restart JBoss AS 7.2, we can see bellow log:

    16:07:21,093 INFO  [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-6) JBAS010400: Bound data source [java:jboss/datasources/ybxiangForumMySqlDataSource]
    ...
    16:07:23,078 INFO  [org.hibernate.Version] (ServerService Thread Pool -- 58) HHH000412: Hibernate Core {4.2.0.CR1}
    16:07:23,109 INFO  [org.hibernate.cfg.Environment] (ServerService Thread Pool -- 58) HHH000206: hibernate.properties not found
    16:07:23,109 INFO  [org.hibernate.cfg.Environment] (ServerService Thread Pool -- 58) HHH000021: Bytecode provider name : javassist
    16:07:23,453 INFO  [org.hibernate.ejb.Ejb3Configuration] (ServerService Thread Pool -- 58) HHH000204: Processing PersistenceUnitInfo [
        name: ybxiang-forum-persistence-unit
        ...]

     

    The blue log means that our configuration in persistence.xml takes effect.

     

     

     

     

    4. class path Configuration

    4.1 EJB project's class path

    • In most cases, we use javax.persistence.*, so, let's add  JPA API jar to  EJB's classpath.
    • Let's add  EJB API jar to  EJB's classpath too.
    • If you want to use JBoss logging, please add related jar to classpath. Of course, we can use JDK logging, which will be processed by JBoss AS 7 perfectly.(More info, refer to JBoss7.1.1 > article > JBoss Logging)
    • We had better to save our password in hash mode into DB, so, we need to include jboss picket box jar in our classpath: we use org.jboss.crypto.CryptoUtil or org.jboss.security.auth.spi.Util to hash our password.

    NOTE, all mentioned jars can be found in  $JBOSS_HOME/modules/system/layers/base.

     

    Now, our EJB project's class path is:

     

     

     

    4.2 WAR project's classpath

    • In most cases, we will use JSF API and servlet API, so let's include them in WAR project's classpath.
    • In most case, we inject our EJB into JSF MBean with annotation “@EJB”, so, EJB API jar should be included in WAR project's classpath.

     

    Now, our WAR project's class path is:   

    5 EAR functions planning

     

    We will implement bellow functions in our EAR application(web site):

    • User registration, account activation, JAAS login, Find Password, email, Console.
    • Display entities in Pagination style.
    • File upload.