Chapter 4. Entity Configuration Files

4.1. Intro

This section talks about various configuration parameters for getting entities to work within JBoss. JBoss EJB 3.0 is built on top of the Hibernate ORM solution, and more specifically, the Hibernate Entity Manager whose documentation comes with your JBoss EJB 3.0 distribution. JBoss EJB 3.0 also requires JBoss JDBC connection pools. You'll learn you to configure both and how they relate to eachother.

4.2. Configuration Files

To use Entity beans within JBoss EJB 3.0 you'll need to do a few things.

  • Configure a JBoss datasource using *-ds.xml file. Check out our documentation or you can view example configurations for many different datasources within: jboss-dist/docs/examples/jca
  • Create a persistence.xml file and jar up your entity classes with the persistence.xml file living in the META-INF/ directory.

4.2.1. Configure JBoss datasource

For datasources, JBoss comes with the Hypersonic SQL database embedded within it and a default datasource available in JNDI under {{java:/DefaultDS}}. Otherwise, you'll need to specify your own datasource. Please refer to the JBoss AS guide on how to create a jBoss connection pool. Also, there are examples in the jboss distrubtion under docs/examples/jca.

4.2.2. persistence.xml and .jar files

For those of you familiar with older versions of the spec, there is no .par file anymore. Entities are placed in a EJB-JAR .jar file or a .jar file all their own. You must also define a persistence.xml file that resides in the META-INF folder of the .jar file. Here's an example of a persistence.xml file.

<persistence>
   <persistence-unit name="manager1">
       <jta-data-source>java:/DefaultDS</jta-data-source>
       <jar-file>../MyApp.jar</jar-file>
       <class>org.acme.Employee</class>
       <class>org.acme.Person</class>
       <class>org.acme.Address</class>
       <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
       </properties>
   </persistence-unit>
</persistence>
          
name

You are required to name your persistence unit. If your persistence classes are within a EJB JAR archive, and it is the only persistence unit defined, then you do not have to reference this name explicitly in your @PersistenceContext and @PersistenceUnit annotations.

jta-data-source, non-jta-data-source

This is the JNDI name of where the javax.sql.DataSource is located. This is ignored when *not* used within an application server. When running outside of an application server, you must specify JDBC connections with Hibernate specific properties (see below). If you're running inside JBoss, put the jndi name of the datasource you defined in the earlier section. Remember to put the "java:/" in front of the jndi name you selected for your datasource.

jar-file and class

The class element specifies a fully qualified classname that you will belong to the persistence unit. The jar-file element specifies another jar you want automatically scanned for @Entity classes. When using jar-file, you must specify a path relative to the jar file the persistence.xml file is in. By default also, the jar the persistence.xml file is placed in is scanned for @Entity classes as well.

properties

The properties element is used to specify vendor specific properties. This is where you will define your JBoss and Hibernate specific configurations.

JBoss EJB 3.0 is built on top of Hibernate 3.0 ORM solution. You may need to provide information to Hibernate so that it knows the database vendor dialect (MySQL, Oracle, etc...), caching, as well as other settings. JBoss EJB 3.0 also has some specific configurable properties as well. Here's a table of properties. We don't list all the Hibernate ones. You can go look in the Hibernate documentation for those.

Table 4.1.  Example Config Properties

Property Description
hibernate.dialect Usually Hibernate can figure out the database dialect itself, but maybe not. Check the hibernate doco for information on this
hibernate.hbm2ddl.auto=update Creates the database schema on deploy if it doesn't exist. Alters it if it has changed. Useful for when you want to generate database schema from entity beans
hibernate.cache.provider_class Defines the caching architecture that Hibernate should use. There is a tutorial to set up a clustered cache.
jboss.entity.manager.jndi.name JBoss does not publish container managed EntityManagers in JNDI by default. Use this to bind it.
jboss.entity.manager.factory.jndi.name JBoss does not publish container managed EntityManagerFactorys in JNDI by default. Use this to bind it.
jboss.no.implicit.datasource.dependency JBoss tries to register deployment dependencies for datasource by guessing the dependency name based on the jndi name of the datasource. Use this switch if the guess is wrong.
jboss.depends.{some arbitrary name} Specify an MBean dependency for the persistence unit deployment.

4.3. EAR and WAR files

JBoss 4.0.x does not support the Java EE 5 EAR format. So, if you want to deploy a standalone persistence archive, you must list it within application.xml as an ejb module.

For WAR files, JBoss 4.0.x does not yet support deploying a persistence archive with WEB-INF/lib as required by the spec.

4.4. Referencing persistence units

4.4.1. Scoped deployments

If a persistence unit is defined in an EJB-JAR file it is not visible to other deployed jars using the @PersistenceContext or @PersistenceUnit annotation. This scoping is required by the specification.

4.4.2. Referencing from Global JNDI

Persistence units are not available within global JNDI unless you explicitly configure them to do so. There are two properties you can specify in your persistence.xml file to enable this. jboss.entity.manager.jndi.name gives you a transaction scoped entity manager you can interact with. jboss.entity.manager.factory.jndi.name binds the entity manager factory into global JNDI.

<persistence>
   <persistence-unit name="manager1">
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <properties>
         <property name="jboss.entity.manager.jndi.name" value="java:/Manager1"/>
         <property name="jboss.entity.manager.factory.jndi.name" value="java:/Manager1Factory"/>
      </properties>
   </persistence-unit>
</persistence>
          

4.5. Securing Entity Beans

There is no spec defined way of security EJB 3.0 entity beans. JBoss does provide a solution but it is only available within the JBoss Application Server. You can secure access to the CRUD operations of your entity, but not method invocations on the entity. Basically, what you are securing is when the Entitymanager does persist(), remove(), etc. operations on an entity. To secure an entity you must add additional property information within persistence.xml. here's an example:

            <?xml version="1.0" encoding="UTF-8"?>
            <persistence>
               <persistence-unit name="tempdb">
                  <jta-data-source>java:/DefaultDS</jta-data-source>
                  <properties>
                      <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
                     <property name="hibernate.jacc.allowed.org.jboss.ejb3.test.jacc.AllEntity" value="insert,update,delete,read"/>
                     <property name="hibernate.jacc.allowed.org.jboss.ejb3.test.jacc.StarEntity" value="*"/>
                     <property name="hibernate.jacc.allowed.org.jboss.ejb3.test.jacc.SomeEntity" value="insert,delete"/>

                     <property name="hibernate.jacc.enabled" value="true"/>
                  </properties>
               </persistence-unit>
            </persistence>
         

The property name has the role and the entity class within it. It is "hiberante.jacc." + role + FQN of entity class.

The value can be one of insert, update, delete, or read. That is the permission. The "*" character can be used to specify all.

Now the configuration gets a bit more complicated. You have to interact with the EntityManager within a secured jacc enabled EJB (session) or secured jacc enabled WAR. For jacc enabling a WAR, see this URL http://wiki.jboss.org/wiki/Wiki.jsp?page=JACC. There is an aspect domain defined for this "JACC Stateless Bean" or "JACC Stateful Bean". For example:

            @javax.ejb.Stateless
            @SecurityDomain ("other")
            @AspectDomain("JACC Stateless Bean")
            public class StatelessBean implements Stateless
            {
               @PersistenceContext
               EntityManager em;

               @PermitAll
               public int unchecked(int i)
               {
                  System.out.println("stateless unchecked");
                  return i;
               }

               @RolesAllowed ("allowed")
               public int checked(int i)
               {
                  System.out.println("stateless checked");
                  return i;
               }
         

You must do similar configuration on Tomcat to jacc enable wars and your servlets.

The final thing you must do is to create an jacc-service.xml file that will go in your deploy directory. This jacc configuration is defined in more detail at http://wiki.jboss.org/wiki/Wiki.jsp?page=JACC.

            

<server>
   <mbean code="org.jboss.security.jacc.DelegatingPolicy"
      name="jboss.security:service=JaccPolicyProvider"
      xmbean-dd="">
      <xmbean>
         <attribute access="read-only" getMethod="getPolicyProxy">
            <description>The java.security.Policy implementation</description>
            <name>PolicyProxy</name>
            <type>java.security.Policy</type>
         </attribute>
         <attribute access="read-write" getMethod="getExternalPermissionTypes"
                    setMethod="setExternalPermissionTypes">
            <description>The types of non-javax.security.jacc permissions that
               should be validated against this policy</description>
            <name>ExternalPermissionTypes</name>
            <type>[Ljava.lang.Class;</type>
         </attribute>
         <operation>
            <name>listContextPolicies</name>
            <return-type>java.lang.String</return-type>
         </operation>
      </xmbean>
      <!-- Not used, just here to test that custom permissions don't break the
      current behavior of javax.security.jacc.* permissions.
      -->
      <attribute name="ExternalPermissionTypes">org.jboss.security.srp.SRPPermission</attribute>
   </mbean>
   <mbean code="org.jboss.security.jacc.SecurityService"
      name="jboss.security:service=JaccSecurityService"
      xmbean-dd="">
      <xmbean>
         <descriptors>
            <injection id="MBeanServerType" setMethod="setMBeanServer" />
            <injection id="ObjectNameType" setMethod="setObjectName" />
         </descriptors>
         <attribute access="read-write" getMethod="getPolicyName" setMethod="setPolicyName">
            <description>The policy provider MBean name</description>
            <name>PolicyName</name>
            <type>javax.management.ObjectName</type>
         </attribute>
         <attribute access="read-write" getMethod="getPolicyAttributeName"
            setMethod="setPolicyAttributeName">
            <description>The Policy attribute name on the PolicyName MBean</description>
            <name>PolicyAttributeName</name>
            <type>java.lang.String</type>
         </attribute>
         <operation>
            <name>start</name>
         </operation>
         <operation>
            <name>stop</name>
         </operation>
      </xmbean>
      <attribute name="PolicyName">jboss.security:service=JaccPolicyProvider</attribute>
      <attribute name="PolicyAttributeName">PolicyProxy</attribute>
   </mbean>
</server>