Help

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.

Hello all, i would try to describe here my effort with Jboss Seam 2.1 on SAP Netweaver JEE5 Composition Environment 7.1 SP3.

Prerequisites:

  1. Installed CE7.1
  2. Installed SAP Netweaver Developer Studio or at least eclipse with SAP Netweaver Developer Studio plugins.
  3. Desired Seam distribution (i use the latest from SVN self made)
  4. installed custom database (i use postgresql 8.3.1)
  5. Some patience

Setup

  • if you wish to use the Richfaces, it should be prepaired. SAP scans all jar-files for known module types. It's deployer finds the @PostConstruct anotation on org.ajax4jsf.context.AjaxContextImpl.decode(FacesContext context) method. As of JEE Specs, the @PostConstruct shouldn't have any parameters and SAP deployer checks it. So i removed this annotation for now.
  • After deployment my web.xml become namespaces. So the richfaces couldn't determine filter names from it. I found in the file

org.ajax4jsf.webapp.WebXml the line

dig.setNamespaceAware(false)

and changed it to

dig.setNamespaceAware(true)

to get the richfaces working.

  • SAP found in javassist.jars MANIFEST.MF the MainClass entry and deployed the javassist as an application client. So i removed also this entry to not to hurt the deployer.
  • I installed the postgresql driver within the telnet console.

Here is the description of how to do it.

Because of CE deployment specific, the project should be packaged within the Develper Studio and also deployed from it.

We need to create a new SAP EAR Jave EE 5 project with SAP libraries support project. The project should has following facets enabled:

  • EAR
  • SAP Application Library Container
  • SAP Datasource
  • SAP Datasource Alias Provider Module
  • SAP Specific Ear Module

Also select the Create deployment descriptor checkbox.

Important! Do not delete the SAP artifacts from EarContent/META-INF folder to avoid the class loading problems with CE (more info here).

Then i added an EJB3 Project (facets: EJB Module, Java, SAP Specific Ejb Module) without orm.xml and client jars and one Dynamic Web (as usual with facet: SAP Specific Web Module,JavaServer Faces ) to my EAR-Project.

Data source

Data sources are configured in a file named data-sources.xml here is the content of my config:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data-sources SYSTEM "data-sources.dtd" >
<data-sources>
  <application-name>Booking</application-name>
  <data-source>           
        <data-source-name>BookingDS</data-source-name>   
<!-- deployed driver name known to SAP -->
    <driver-name>POSTGRESQL</driver-name>    
<!-- Should be so -->
    <sql-engine>Vendor_SQL</sql-engine>   
    <jdbc-1.x>
<!-- your driver --> 
    <driver-class-name>org.postgresql.Driver</driver-class-name>
<!-- connection uri -->
      <url>jdbc:postgresql:booking</url>

      <user-name>user</user-name>
      <password>password</password>    
    </jdbc-1.x>   
  </data-source>
</data-sources>

I also tried it with XA datasource and it works. But it is not allowed to operate on XA datasource from the remote client, so the hibernate console can not obtain a connection with it.

The DS are bound to JNDI under the jdbc/ namespace. If you are getting troubles with orpersistence- folder (see below), create also a datasource alias to make SAP happy. It can be made in a file named data-source-aliases.xml.

<?xml version="1.0" encoding="UTF-8"?>
<data-source-aliases xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="data-source-aliases.xsd">
  <application-name>Booking</application-name>
  <aliases>
    <data-source-name>BookingDS</data-source-name>
    <alias>jdbc/BookingDS</alias>
  </aliases>
</data-source-aliases>

EAR Project adaption

Add following modules to J2EE Module Dependencies - your BookingEjb.jar, BookingWeb.war, jboss-seam.jar, richfaces-api.jar

Add all other EAR Dependencies to BookingEar project as Bundled Libraries.

antlr-runtime.jar
antlr.jar
asm.jar                             
cglib.jar
commons-collections.jar             
commons-logging.jar
dom4j.jar                           
drools-compiler.jar
drools-core.jar
hibernate-annotations.jar
hibernate-commons-annotations.jar
hibernate-entitymanager.jar
hibernate-search.jar                
hibernate-validator.jar
hibernate.jar                       
javassist.jar                       
jboss-el.jar
jbpm-jpdl.jar                       
log4j.jar
lucene-core.jar                     
mvel14.jar
slf4j-api.jar                       
slf4j-impl.jar

Add

<module>
    <ejb>jboss-seam.jar</ejb>
</module>

to the application.xml

EJB Module

Add all sources from booking example to ejb module. Do not forget seam.properties and component.properties files! Remove all SAP artifacts from META-INF/ folder (possible it needs something to prevent the creation of orpersistence folder in the deployed artifact but i don't know what :-( ).

Change persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" 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">
        <persistence-unit name="BookingEjb">      
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>jdbc/BookingDS</jta-data-source>      
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
         <property name="hibernate.hbm2ddl.auto" value="update"/>
         <property name="hibernate.show_sql" value="true"/>
         <property name="hibernate.format_sql" value="true"/>
          <property name="hibernate.transaction.manager_lookup_class" value="persistence.util.SAPWebASTransactionManagerLookup"/>
         <property name="hibernate.query.jpaql_strict_compliance" value="false" />
         <property name="hibernate.connection.isolation" value="2" />
      </properties>
   </persistence-unit>
</persistence>

Adding of dependencies from EAR-libs doesn't work for me, i added the required libs to build path and didn't export them.

Create class persistence.util.SAPWebASTransactionManagerLookup for obtaining of jndi references to the TM or UT:

package persistence.util;

import org.hibernate.transaction.JNDITransactionManagerLookup;

public class SAPWebASTransactionManagerLookup extends
                JNDITransactionManagerLookup {

        @Override
        protected String getName() {

                return "TransactionManager";
        }

        public String getUserTransactionName() {
                return "UserTransaction";
        }

}

components.properties:

jndiPattern=java:comp/env/\#{ejbName}

The ejb-jar.xml should be intercepted by seam:

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar 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/ejb-jar_3_0.xsd"
        version="3.0">
        

        <interceptors>
                <interceptor>
                        <interceptor-class>
                                org.jboss.seam.ejb.SeamInterceptor
                        </interceptor-class>
                </interceptor>
        </interceptors>

        <assembly-descriptor>
                <interceptor-binding>
                        <ejb-name>*</ejb-name>
                        <interceptor-class>
                                org.jboss.seam.ejb.SeamInterceptor
                        </interceptor-class>
                </interceptor-binding>
        </assembly-descriptor>
</ejb-jar>

And leave the MANIFEST.MF of EJB-Module unchanged!

Also place here the import.sql file for initial filling of tables.

Dynamic Web Module

Now comes the adaption of the web-app

web.xml

Because of complex JNDI-pattern of session bean names in NW CE7.1 (

ejb:/<namespace prefix e.g. sap.com>/<EAR-App name>/<bean class name (w/o package)>/<full qualified local/remote interface name> 

Example for RegisterAction

ejb:/sap.com/RegisterAction/org.jboss.seam.example.booking.Register

)

we should also register the session beans in web.xml. Just add following text to web.xml:

        <ejb-local-ref>
                <ejb-ref-name>EjbSynchronizations</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <local>
                        org.jboss.seam.transaction.LocalEjbSynchronizations
                </local>
                <ejb-link>EjbSynchronizations</ejb-link>
        </ejb-local-ref>
        <ejb-local-ref>
                <ejb-ref-name>TimerServiceDispatcher</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <local>org.jboss.seam.async.LocalTimerServiceDispatcher</local>
                <ejb-link>TimerServiceDispatcher</ejb-link>
        </ejb-local-ref>

        <ejb-local-ref>
                <ejb-ref-name>AuthenticatorAction</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <local>org.jboss.seam.example.booking.Authenticator</local>
                <ejb-link>AuthenticatorAction</ejb-link>
        </ejb-local-ref>

        <ejb-local-ref>
                <ejb-ref-name>BookingListAction</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <local>org.jboss.seam.example.booking.BookingList</local>
                <ejb-link>BookingListAction</ejb-link>
        </ejb-local-ref>

        <ejb-local-ref>
                <ejb-ref-name>ChangePasswordAction</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <local>org.jboss.seam.example.booking.ChangePassword</local>
                <ejb-link>ChangePasswordAction</ejb-link>
        </ejb-local-ref>
        <ejb-local-ref>
                <ejb-ref-name>RegisterAction</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <local>org.jboss.seam.example.booking.Register</local>
                <ejb-link>RegisterAction</ejb-link>
        </ejb-local-ref>
        <ejb-local-ref>
                <ejb-ref-name>HotelSearchingAction</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <local>org.jboss.seam.example.booking.HotelSearching</local>
                <ejb-link>HotelSearchingAction</ejb-link>
        </ejb-local-ref>
        <ejb-local-ref>
                <ejb-ref-name>HotelBookingAction</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <local>org.jboss.seam.example.booking.HotelBooking</local>
                <ejb-link>HotelBookingAction</ejb-link>
        </ejb-local-ref>

I also made the data source shareble here, but i don't know if and how it works:

        <resource-ref>
                <res-ref-name>jdbc/BookingDS</res-ref-name>
                <res-type>javax.sql.DataSource</res-type>
                <res-auth>Container</res-auth>              
                <res-sharing-scope>Shareable</res-sharing-scope>
        </resource-ref>

components.xml

The CE starts the web-apps only on demand. So after the first access to any resource from the application it starts up. In this case the hibernate auto ddl-exporter (triggered with create-drop) produces an exception because it tries to obtain a jdbc connection from the running transaction. It occurs during the first session bean (in case of booking example AuthenticatorAction) is getting intercepted. The session factory is building and hibernate is trying to export the ddl. I thought, the sharing of data source can help, but it didn't. In this case i can suppose two workarounds:

  1. you instantiate the EMF from components.xml with a startup=true or
  2. you use the hibernate console to export the ddl. In this case, the jndi.properties should be filled
java.naming.factory.initial=com.sap.engine.services.jndi.InitialContextFactoryImpl
java.naming.provider.url=<host>:5<instance nr>04 #(e.g. instance nr. = 00 -> 50004)
java.naming.security.principal=<user>
java.naming.security.credentials=<password>

and you need also some SAP-Libraries in a class path of hibernate tools configuration:

sap.com~tc~exception~impl.jar
sap.com~tc~je~clientlib~impl.jar
sap.com~tc~je~naming~impl.jar
<jdbc.driver.of.the desired db>.jar

I use the persistence.xml from my ejb module as a hibernate tools configuration and it works just fine.

If you wish to initialize the EMF on startup, change the components.xml as following:

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns="http://jboss.com/products/seam/components"
            xmlns:core="http://jboss.com/products/seam/core"
            xmlns:security="http://jboss.com/products/seam/security"
            xmlns:transaction="http://jboss.com/products/seam/transaction"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:persistence="http://jboss.com/products/seam/persistence"
            xsi:schemaLocation=
                "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.1.xsd
                 http://jboss.com/products/seam/transaction http://jboss.com/products/seam/transaction-2.1.xsd
                 http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.1.xsd
                 http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.1.xsd
                 http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.1.xsd">

    <core:init jndi-pattern="@jndiPattern@" debug="true"/>

    <core:manager conversation-timeout="120000"
                  concurrent-request-timeout="500"
                  conversation-id-parameter="cid"/>
        <!-- here the important part -->
        <persistence:entity-manager-factory
                persistence-unit-name="BookingEjb" name="emf"
                auto-create="true" startup="true"/>
        <!-- endless loop due to exeption "No session" or so -->
<!--    <transaction:ejb-transaction/> -->

    <security:identity authenticate-method="#{authenticator.authenticate}"/>

</components>

Do not forget to add the necessary libraries to WEB-INF/lib. In my case these are:

commons-beanutils.jar
commons-digester.jar
jboss-seam-debug.jar
jboss-seam-ui.jar
jsf-facelets.jar
richfaces-impl.jar
richfaces-ui.jar

If you have done all as i described above, after deployment you should get the booking example working on SAP NW CE7.1!

Debugging

The remote debugging of the application is possible. You should start the desired server node in debug mode. The debug port number has following pattern

5<Instance Nr.>(26 + node number)

In my case the instance has got the number 00 and the node the number 0 so the debug port number is 50026.

Problems

There are some problems which prevent the jboss seam enabled application from beening smoothly integrated into CE7.1

  • I didn't get the ejb transaction synchronizer working (via <transaction:ejb-transaction/> ) so i commented it out for now. I've got some kind session doesn't exist exception i think in a @Destroy callback of EjbSynchronizations.
  • During the interseption of stateless session bean AuthenticatorAction, in @PostConstruct callback, some SAP EJB3.0 specs checker threw an exception EntityManager access is forbidden according EJB spec. After i have changed the AuthenticatorAction to @Stateful it works. I think, it could be a bug in SAP implementation of EJB3, because the EntityManager access is not allowed only for Entity-Lifecycle callbacks (here i also don't understand why, but it is so) and is allowed for session beans.
  • After undeployment, the seam-jars can not be deleted via undeployer and still be locked. Only the restart of the whole JEE instance helps. It's a huge drawback, in my opinion, because the restart takes about 10 minutes!
  • In the target folder of the deployed app SAP creates the folder named orpersistence and copies there my ejb.jar. I couldn't prevent CE-deployer from doing it. If some one knows a workaround (possible some SAP XML artifact, as in case of class loading problem - see above), i would be grateful to hear it.

That's all for now.

Gena

PS. At this point i can only wish all explorer of SAP NW CE7.1 (with or without Seam) good luck!