Datenbankzugriff mit EJB / CMP

GartenUmgraben

Erfahrenes Mitglied
Moin..

Ich muss mit Eclipse eine Anwendung programmieren durch die ich unter Nutzung von EJB und CMP auf eine MySQL Datenbank zugreifen kann, also weg vom getConnection und ResultSet..... Allerdings sind die Tutorials ec. die ich bisher im Netz gefunden habe eher mager. Hat jemand eine gutes und simples Tutorial wo die wichtigsten Dinge erklärt sind ? Also sprich welche Beans, xmls ec brauche ich und in welcher Bean wird was aufgerufen bzw. erzeugt usw.


Bin für jede Hilfe dankbar
 
Hallo!

Als Beispielanwendung wollen wir eine minimale Personenverwaltung bauen.
Personen werden in einer MySQL Datenbankgespeichert und mittels einer
CMP EntityBean "dargestellt". Die Zugriffsart auf diese EntityBean belassen
wir auf "local". Mit der local EntityBean interagieren wir über eine
SessionBean welche per "Remote" zugreifbar ist. Um die EntityBean von der SessionBean aus zu finden (bzw. das LocalHomeInterface) bedienen wir uns des ServiceLocator Patterns. Die Daten werden über ein ValueObject zum Client Transportiert. Der Client hat KEINEN direkten
Zugriff auf die EntityBean.

Das Notwendige Datenbankschema für die Testdatenbank lassen wir vom JBoss beim Deployen automatisch erstellen.

Zum nachvollziehen des ganzen einfach das angehägte Projekt in Eclipse importieren.
(Damit alles korrekt funktioniert solltet ihr das JBoss IDE Plugin und den JBoss 3.2.xinstalliert haben (dmit hab ichs getestet))
Bauen lassen kann man alles über das Ant Build-Skript (build.xml -> Kontextmenü Run as Ant Build).

Durch den build wird im Verzeichnis deploy eine Datei namens tutorials-ejb-example.jar erstellt. Diese könnt ihr entweder mittels der Kontextmenü Option Deploy To ... (Server in JBoss IDE muss zuvor konfiguriert werden) oder per einfachen File Copy ins deploy Verzeichnis des default JBoss Servers unter %JBoss_HOME%/server/default/deploy ablegen ... hat alles geklappt solltet ihr bei erfolgreichem Deployment:
Code:
22:01:05,046 INFO  [EjbModule] Deploying Person
22:01:05,062 INFO  [EjbModule] Deploying PersonService
22:01:05,531 INFO  [EJBDeployer] Deployed: file:/E:/jboss/3.2.7/server/default/deploy/tutorials-ejb-example.jar
in der Konsole sehen können.

...

Wir wollen Personen anlegen/löschen und per Namen / ID wiederfinden.

Okay fangen wir mal an:

Zuerst müssen wir den MySQL Treiber (Z.bsp.: mysql-connector-java-3.1.8-bin.jar) ins jeweilige Server-
verzeichnis kopieren. (Z.bsp. server/default /lib) Die Unterverzeichnisse
unterhalb von server stellen Verschiedene Laufzeitkonfigurationen des JBoss dar.

MySQL Datasource anlegen:
Code:
<?xml version="1.0" encoding="UTF-8"?>

<!-- $Id: mysql-ds.xml,v 1.1.2.2 2004/12/01 11:36:28 schrouf Exp $ -->
<!--  Datasource config for MySQL using 3.0.9 available from:
http://www.mysql.com/downloads/api-jdbc-stable.html
-->

<datasources>
  <local-tx-datasource>
    <jndi-name>MySqlDS</jndi-name>
    <connection-url>jdbc:mysql://localhost:3306/test</connection-url>
    <driver-class>com.mysql.jdbc.Driver</driver-class>
    <user-name>root</user-name>
    <password></password>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
    <!-- sql to call when connection is created
    <new-connection-sql>some arbitrary sql</new-connection-sql>
      -->
    <!-- sql to call on an existing pooled connection when it is obtained from pool 
    <check-valid-connection-sql>some arbitrary sql</check-valid-connection-sql>
      -->
  </local-tx-datasource>
</datasources>
-> mysql-ds.xml ins server/default/deploy Verzeichnis kopieren
Die Datenquelle ist nun Beispielsweise unter dem JNDI Namen (java:/MySqlDS)
verfügbar -> Log Meldungen beachten.

Unsere CMP-EntityBean (mit XDoclet-Kommentaren zur Codegenerierung angereichert) sähe dann so aus:
Code:
/*
 * Created on 06.05.2005@19:01:35
 *
 * TODO Add some Licence info
 */
package de.tutorials.ejb.domain;

import java.rmi.RemoteException;

import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.RemoveException;

/**
 * @ejb.bean name="Person" display-name="Person" primkey-field = "id"
 *           description="Description for Person" type="CMP" cmp-version="2.x"
 *           view-type="local"
 * 
 * @ejb.value-object generatePKConstructor = "true" name = "Person"
 * 
 * @ejb.finder signature = "Person findPersonByName(java.lang.String name)"
 *             description = "Find Person by Name" query = "SELECT OBJECT(p) FROM Person AS p WHERE p.name=?1"
 * 
 * @jboss.persistence create-table = "true" datasource = "java:/MySqlDS"
 *                    datasource-mapping = "mySQL" table-name = "person"
 * 
 *  
 */
public abstract class PersonBean implements EntityBean {

    /**
     * @ejb.create-method view-type = "local"
     * @param id
     * @return
     * @throws CreateException
     */
    public Integer ejbCreate(Integer id) throws CreateException {
        setId(id);
        return null;
    }

    public void ejbPostCreate(Integer id) {

    }

    /**
     *  
     */
    public PersonBean() {
        super();
        // TODO Auto-generated constructor stub
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.ejb.EntityBean#setEntityContext(javax.ejb.EntityContext)
     */
    public void setEntityContext(EntityContext ctx) throws EJBException,
            RemoteException {
        // TODO Auto-generated method stub

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.ejb.EntityBean#unsetEntityContext()
     */
    public void unsetEntityContext() throws EJBException, RemoteException {
        // TODO Auto-generated method stub

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.ejb.EntityBean#ejbRemove()
     */
    public void ejbRemove() throws RemoveException, EJBException,
            RemoteException {
        // TODO Auto-generated method stub

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.ejb.EntityBean#ejbActivate()
     */
    public void ejbActivate() throws EJBException, RemoteException {
        // TODO Auto-generated method stub

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.ejb.EntityBean#ejbPassivate()
     */
    public void ejbPassivate() throws EJBException, RemoteException {
        // TODO Auto-generated method stub

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.ejb.EntityBean#ejbLoad()
     */
    public void ejbLoad() throws EJBException, RemoteException {
        // TODO Auto-generated method stub

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.ejb.EntityBean#ejbStore()
     */
    public void ejbStore() throws EJBException, RemoteException {
        // TODO Auto-generated method stub

    }

    public abstract void setId(Integer id);

    /**
     * @ejb.interface-method
     * @ejb.pk-field
     * @ejb.persistence column-name = "id"
     * @ejb.value-object
     * @return
     */
    public abstract Integer getId();

    /**
     * @ejb.interface-method
     * @ejb.persistence column-name = "name"
     * @ejb.value-object
     * @return
     */
    public abstract String getName();

    /**
     * @ejb.interface-method
     * @ejb.value-object
     * @return
     */
    public abstract void setName(String name);

}

Per XDoclet lassen wir uns das Local und das Localhome Interface dazu generieren:
Local:
Code:
/*
* 
Generated by XDoclet - Do not edit!
*/
package de.tutorials.ejb.domain.generated;
/**
* Local interface for Person.
*/
public interface PersonLocal extends javax.ejb.EJBLocalObject {
public java.lang.Integer getId();
public java.lang.String getName();
public void setName(java.lang.String name);
}

LocalHome:
Code:
/*
 * Generated by XDoclet - Do not edit!
 */
package de.tutorials.ejb.domain.generated;

/**
 * Local home interface for Person.
 */
public interface PersonLocalHome
   extends javax.ejb.EJBLocalHome
{
   public static final String COMP_NAME="java:comp/env/ejb/PersonLocal";
   public static final String JNDI_NAME="PersonLocal";

   public de.tutorials.ejb.domain.generated.PersonLocal create(java.lang.Integer id)
      throws javax.ejb.CreateException;

   public de.tutorials.ejb.domain.generated.PersonLocal findPersonByName(java.lang.String name)
      throws javax.ejb.FinderException;

   public de.tutorials.ejb.domain.generated.PersonLocal findByPrimaryKey(java.lang.Integer pk)
      throws javax.ejb.FinderException;

}

Das dazu passende ValueObject PersonValue:
Code:
/*
 * Generated by XDoclet - Do not edit!
 */
package de.tutorials.ejb.domain.genrated.vo;

/**
 * Value object for Person.
 *  
 */
public class PersonValue extends java.lang.Object implements
        java.io.Serializable {
    private java.lang.Integer id;

    private boolean idHasBeenSet = false;

    private java.lang.String name;

    private boolean nameHasBeenSet = false;

    private java.lang.Integer pk;

    public PersonValue() {
    }

    public PersonValue(java.lang.Integer id, java.lang.String name) {
        this.id = id;
        idHasBeenSet = true;
        this.name = name;
        nameHasBeenSet = true;
        pk = this.getId();
    }

    //TODO Cloneable is better than this !
    public PersonValue(PersonValue otherValue) {
        this.id = otherValue.id;
        idHasBeenSet = true;
        this.name = otherValue.name;
        nameHasBeenSet = true;

        pk = this.getId();
    }

    public java.lang.Integer getPrimaryKey() {
        return pk;
    }

    public void setPrimaryKey(java.lang.Integer pk) {
        // it's also nice to update PK object - just in case
        // somebody would ask for it later...
        this.pk = pk;
        setId(pk);
    }

    public java.lang.Integer getId() {
        return this.id;
    }

    public void setId(java.lang.Integer id) {
        this.id = id;
        idHasBeenSet = true;

        pk = id;
    }

    public boolean idHasBeenSet() {
        return idHasBeenSet;
    }

    public java.lang.String getName() {
        return this.name;
    }

    public void setName(java.lang.String name) {
        this.name = name;
        nameHasBeenSet = true;

    }

    public boolean nameHasBeenSet() {
        return nameHasBeenSet;
    }

    public String toString() {
        StringBuffer str = new StringBuffer("{");

        str.append("id=" + getId() + " " + "name=" + getName());
        str.append('}');

        return (str.toString());
    }

    /**
     * A Value Object has an identity if the attributes making its Primary Key
     * have all been set. An object without identity is never equal to any other
     * object.
     * 
     * @return true if this instance has an identity.
     */
    protected boolean hasIdentity() {
        return idHasBeenSet;
    }

    public boolean equals(Object other) {
        if (this == other)
            return true;
        if (!hasIdentity())
            return false;
        if (other instanceof PersonValue) {
            PersonValue that = (PersonValue) other;
            if (!that.hasIdentity())
                return false;
            boolean lEquals = true;
            if (this.id == null) {
                lEquals = lEquals && (that.id == null);
            } else {
                lEquals = lEquals && this.id.equals(that.id);
            }

            lEquals = lEquals && isIdentical(that);

            return lEquals;
        } else {
            return false;
        }
    }

    public boolean isIdentical(Object other) {
        if (other instanceof PersonValue) {
            PersonValue that = (PersonValue) other;
            boolean lEquals = true;
            if (this.name == null) {
                lEquals = lEquals && (that.name == null);
            } else {
                lEquals = lEquals && this.name.equals(that.name);
            }

            return lEquals;
        } else {
            return false;
        }
    }

    public int hashCode() {
        int result = 17;
        result = 37 * result + ((this.id != null) ? this.id.hashCode() : 0);

        result = 37 * result + ((this.name != null) ? this.name.hashCode() : 0);

        return result;
    }

}

....
 

Anhänge

Unseren ServiceLocator mit dem wir den lookup nach den EJB komponenten bewerkstelligen:

Code:
/*
 * Created on 06.05.2005@20:11:11
 *
 * TODO Add some Licence info
 */
package de.tutorials.ejb.service;

import java.util.HashMap;
import java.util.Map;

import javax.ejb.EJBHome;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

/**
 * @author Tom
 * 
 * TODO Describe me
 */
public class ServiceLocator {
    private static Map cashedHomes = new HashMap();

    private static InitialContext ctx;

    private static ServiceLocator serviceLocator = new ServiceLocator();

    protected ServiceLocator() {
        try {
            ctx = new InitialContext();
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }

    /**
     * @return Returns the serviceLocator.
     */
    public static ServiceLocator getServiceLocator() {
        return serviceLocator;
    }

    public Object lookup(String jndiName, Class homeClazz) {

        if (cashedHomes.containsKey(jndiName)) {
            return (EJBHome) cashedHomes.get(jndiName);
        }

        Object home = null;
        try {
            home = ctx.lookup(jndiName);
            home = PortableRemoteObject.narrow(home, homeClazz);
            cashedHomes.put(jndiName, home);
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return home;
    }
}

Unsere SessionBean PersonServiceBean:
Code:
/*
 * Created on 06.05.2005@19:09:34
 *
 * TODO Add some Licence info
 */
package de.tutorials.ejb.service;

import java.rmi.RemoteException;

import javax.ejb.EJBException;
import javax.ejb.FinderException;
import javax.ejb.RemoveException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

import javax.ejb.CreateException;

import de.tutorials.ejb.domain.PersonBean;
import de.tutorials.ejb.domain.generated.PersonLocal;
import de.tutorials.ejb.domain.generated.PersonLocalHome;
import de.tutorials.ejb.domain.genrated.vo.PersonValue;

/**
 * @ejb.bean name="PersonService" display-name="PersonService"
 *           description="Description for PersonService" type="Stateless"
 *           view-type="remote"
 */
public class PersonServiceBean implements SessionBean {

    /**
     *  
     */
    public PersonServiceBean() {
        super();
        // TODO Auto-generated constructor stub
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)
     */
    public void setSessionContext(SessionContext ctx) throws EJBException,
            RemoteException {
        // TODO Auto-generated method stub

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.ejb.SessionBean#ejbRemove()
     */
    public void ejbRemove() throws EJBException, RemoteException {
        // TODO Auto-generated method stub

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.ejb.SessionBean#ejbActivate()
     */
    public void ejbActivate() throws EJBException, RemoteException {
        // TODO Auto-generated method stub

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.ejb.SessionBean#ejbPassivate()
     */
    public void ejbPassivate() throws EJBException, RemoteException {
        // TODO Auto-generated method stub

    }

    /**
     * Default create method
     * 
     * @throws CreateException
     * @ejb.create-method
     */
    public void ejbCreate() throws CreateException {

    }

    /**
     * @ejb.interface-method view-type = "remote"
     * @param id
     * @param name
     */
    public void createPerson(Integer id, String name) {
        PersonLocalHome personHome = (PersonLocalHome) ServiceLocator
                .getServiceLocator().lookup(PersonLocalHome.JNDI_NAME,
                        PersonLocalHome.class);

        try {
            PersonLocal personLocal = personHome.create(id);
            personLocal.setName(name);
        } catch (CreateException e) {
            e.printStackTrace();
        }
    }

    /**
     * @ejb.interface-method view-type = "remote"
     * @param id
     * @param name
     */
    public PersonValue findPersonById(Integer id) {

        PersonLocalHome personHome = (PersonLocalHome) ServiceLocator
                .getServiceLocator().lookup(PersonLocalHome.JNDI_NAME,
                        PersonLocalHome.class);

        try {
            PersonLocal personLocal = personHome.findByPrimaryKey(id);
            Integer personId = personLocal.getId();
            String name = personLocal.getName();

            PersonValue personValue = new PersonValue(personId, name);

            return personValue;

        } catch (FinderException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * @ejb.interface-method view-type = "remote"
     * @param id
     * @param name
     */
    public PersonValue findPersonByName(String name) {

        PersonLocalHome personHome = (PersonLocalHome) ServiceLocator
                .getServiceLocator().lookup(PersonLocalHome.JNDI_NAME,
                        PersonLocalHome.class);

        try {
            PersonLocal personLocal = personHome.findPersonByName(name);
            Integer personId = personLocal.getId();
            String personName = personLocal.getName();

            PersonValue personValue = new PersonValue(personId, name);

            return personValue;

        } catch (FinderException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * @ejb.interface-method view-type = "remote"
     * @param id
     * @param name
     */
    public void deletePersonById(Integer id) {

        PersonLocalHome personHome = (PersonLocalHome) ServiceLocator
                .getServiceLocator().lookup(PersonLocalHome.JNDI_NAME,
                        PersonLocalHome.class);

        try {
            personHome.remove(id);
        } catch (EJBException e) {
            e.printStackTrace();
        } catch (RemoveException e) {
            e.printStackTrace();
        }
    }

}

Das dazugehörige Remote Interface PersonService:
Code:
/*
 * Generated by XDoclet - Do not edit!
 */
package de.tutorials.ejb.service.generated;

/**
 * Remote interface for PersonService.
 */
public interface PersonService
   extends javax.ejb.EJBObject
{

   public void createPerson( java.lang.Integer id,java.lang.String name )
      throws java.rmi.RemoteException;

   public de.tutorials.ejb.domain.genrated.vo.PersonValue findPersonById( java.lang.Integer id )
      throws java.rmi.RemoteException;

   public de.tutorials.ejb.domain.genrated.vo.PersonValue findPersonByName( java.lang.String name )
      throws java.rmi.RemoteException;

   public void deletePersonById( java.lang.Integer id )
      throws java.rmi.RemoteException;

}

Und das HomeInterface PersonServiceHome:
Code:
/*
 * Generated by XDoclet - Do not edit!
 */
package de.tutorials.ejb.service.generated;

/**
 * Home interface for PersonService.
 */
public interface PersonServiceHome
   extends javax.ejb.EJBHome
{
   public static final String COMP_NAME="java:comp/env/ejb/PersonService";
   public static final String JNDI_NAME="PersonService";

   public de.tutorials.ejb.service.generated.PersonService create()
      throws javax.ejb.CreateException,java.rmi.RemoteException;

}

Die DeploymentDescriptoren ejb-jar.xml, jbosscmp-jdbc.xml und jboss.xml
jboss.xml:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.2//EN" "http://www.jboss.org/j2ee/dtd/jboss_3_2.dtd">

<jboss>

   <enterprise-beans>

     <!--
       To add beans that you have deployment descriptor info for, add
       a file to your XDoclet merge directory called jboss-beans.xml that contains
       the <session></session>, <entity></entity> and <message-driven></message-driven>
       markup for those beans.
     -->

      <entity>
         <ejb-name>Person</ejb-name>
         <local-jndi-name>PersonLocal</local-jndi-name>

        <method-attributes>
        </method-attributes>

      </entity>

      <session>
         <ejb-name>PersonService</ejb-name>
         <jndi-name>PersonService</jndi-name>

        <method-attributes>
        </method-attributes>
      </session>

   </enterprise-beans>

   <resource-managers>
   </resource-managers>

  <!--
    | for container settings, you can merge in jboss-container.xml
    | this can contain <invoker-proxy-bindings/> and <container-configurations/>
  -->

</jboss>
 
jbosscmp-jdbc.xml:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jbosscmp-jdbc PUBLIC "-//JBoss//DTD JBOSSCMP-JDBC 3.2//EN" "http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_3_2.dtd">

<jbosscmp-jdbc>
   <defaults>
   </defaults>

   <enterprise-beans>

     <!--
       To add beans that you have deployment descriptor info for, add
       a file to your XDoclet merge directory called jbosscmp-jdbc-beans.xml
       that contains the <entity></entity> markup for those beans.
     -->

      <entity>
         <ejb-name>Person</ejb-name>
		 <datasource>java:/MySqlDS</datasource>
		 <datasource-mapping>mySQL</datasource-mapping>
         <create-table>true</create-table>

         <table-name>person</table-name>

         <cmp-field>
            <field-name>id</field-name>
            <column-name>id</column-name>

        </cmp-field>
         <cmp-field>
            <field-name>name</field-name>
            <column-name>name</column-name>

        </cmp-field>

<!-- jboss 3.2 features -->
<!-- optimistic locking does not express the exclusions needed -->
      </entity>

   </enterprise-beans>

</jbosscmp-jdbc>

ejb-jar.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">

<ejb-jar >

   <description><![CDATA[No Description.]]></description>
   <display-name>Generated by XDoclet</display-name>

   <enterprise-beans>

      <!-- Session Beans -->
      <session >
         <description><![CDATA[Description for PersonService]]></description>
         <display-name>PersonService</display-name>

         <ejb-name>PersonService</ejb-name>

         <home>de.tutorials.ejb.service.generated.PersonServiceHome</home>
         <remote>de.tutorials.ejb.service.generated.PersonService</remote>
         <ejb-class>de.tutorials.ejb.service.PersonServiceBean</ejb-class>
         <session-type>Stateless</session-type>
         <transaction-type>Container</transaction-type>

      </session>

     <!--
       To add session beans that you have deployment descriptor info for, add
       a file to your XDoclet merge directory called session-beans.xml that contains
       the <session></session> markup for those beans.
     -->

      <!-- Entity Beans -->
      <entity >
         <description><![CDATA[Description for Person]]></description>
         <display-name>Person</display-name>

         <ejb-name>Person</ejb-name>

         <local-home>de.tutorials.ejb.domain.generated.PersonLocalHome</local-home>
         <local>de.tutorials.ejb.domain.generated.PersonLocal</local>

         <ejb-class>de.tutorials.ejb.domain.PersonBean</ejb-class>
         <persistence-type>Container</persistence-type>
         <prim-key-class>java.lang.Integer</prim-key-class>
         <reentrant>False</reentrant>
         <cmp-version>2.x</cmp-version>
         <abstract-schema-name>Person</abstract-schema-name>
         <cmp-field >
            <description><![CDATA[]]></description>
            <field-name>id</field-name>
         </cmp-field>
         <cmp-field >
            <description><![CDATA[]]></description>
            <field-name>name</field-name>
         </cmp-field>
          <primkey-field>id</primkey-field>

         <query>
            <description><![CDATA[Find Person by Name]]></description>
            <query-method>
               <method-name>findPersonByName</method-name>
               <method-params>
                  <method-param>java.lang.String</method-param>
               </method-params>
            </query-method>
            <ejb-ql><![CDATA[SELECT OBJECT(p) FROM Person AS p WHERE p.name=?1]]></ejb-ql>
         </query>
	  <!-- Write a file named ejb-finders-PersonBean.xml if you want to define extra finders. -->
      </entity>

     <!--
       To add entity beans that you have deployment descriptor info for, add
       a file to your XDoclet merge directory called entity-beans.xml that contains
       the <entity></entity> markup for those beans.
     -->

      <!-- Message Driven Beans -->
     <!--
       To add message driven beans that you have deployment descriptor info for, add
       a file to your XDoclet merge directory called message-driven-beans.xml that contains
       the <message-driven></message-driven> markup for those beans.
     -->

   </enterprise-beans>

   <!-- Relationships -->

   <!-- Assembly Descriptor -->
     <!--
       To specify your own assembly descriptor info here, add a file to your
       XDoclet merge directory called assembly-descriptor.xml that contains
       the <assembly-descriptor></assembly-descriptor> markup.
     -->

   <assembly-descriptor >
     <!--
       To specify additional security-role elements, add a file in the merge
       directory called ejb-security-roles.xml that contains them.
     -->

   <!-- method permissions -->
     <!--
       To specify additional method-permission elements, add a file in the merge
       directory called ejb-method-permissions.ent that contains them.
     -->

   <!-- finder permissions -->

   <!-- finder permissions -->

   <!-- transactions -->
     <!--
       To specify additional container-transaction elements, add a file in the merge
       directory called ejb-container-transaction.ent that contains them.
     -->

   <!-- finder transactions -->

     <!--
       To specify an exclude-list element, add a file in the merge directory
       called ejb-exclude-list.xml that contains it.
     -->
   </assembly-descriptor>

</ejb-jar>

Was natürlich nciht fehlen darf: Der Client..
EjbClient:
Code:
/*
 * Created on 06.05.2005@20:59:05
 *
 * TODO Add some Licence info
 */
package de.tutorials.ejb.client;

import java.util.Hashtable;

import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;

import de.tutorials.ejb.service.generated.PersonService;
import de.tutorials.ejb.service.generated.PersonServiceHome;

/**
 * @author Tom
 * 
 * TODO Describe me
 */
public class EjbClient {

    public static void main(String[] args) throws Exception {

        Hashtable env = new Hashtable();
        env.put("java.naming.factory.initial",
                "org.jnp.interfaces.NamingContextFactory");
        env.put("java.naming.factory.url.pkgs",
                "org.jboss.naming:org.jnp.interfaces");
        env.put("java.naming.provider.url", "jnp://localhost:1099");

        InitialContext ctx = new InitialContext(env);
        PersonServiceHome personServiceHome = (PersonServiceHome) PortableRemoteObject
                .narrow(ctx.lookup(PersonServiceHome.JNDI_NAME),
                        PersonServiceHome.class);

        PersonService personService = personServiceHome.create();

        //Person anlegen:
        //        personService.createPerson(Integer.valueOf(1), "Thomas");

        //Person finden über PK
        //        PersonValue person =
        // personService.findPersonById(Integer.valueOf(1));
        //        System.out.println(person);

        //Person finden über Namen
        //        PersonValue person = personService.findPersonByName("Thomas");
        //        System.out.println(person);

        //Person löschen
        //personService.deletePersonById(Integer.valueOf(1));

    }
}

HTH
Gruß Tom
 
Wie man sieht ist das eine *sehr einfache* EJB Anwendung ;-)
Dinge wie Transaktions Management per CMT (Container Managed Transactions) oder CMR (Container Managed Relations) habe ich der einfachheit halber *g* nicht mit eingebracht.

Wie man sicherlich erkennen kann ist EJB nicht gerade eine einsteigerfreundliche Technologie ... zumindest nicht in der Version <= 2.x der EJB Spezifikation. Da gibt es heutzutage doch einige Frameworks die das selbe wie EJB mit CMP / CMT etc. ein wenig "einfacher/pragmatischer/eleganter(?) angehen" -> Z.Bsp. die Kombination aus Springframework und Hibernate :)

Aber warten wir mal ab wie sich EJB 3.0 entwickelt....

//Btw. die ServiceLocator Implementierung ist so natürlich Käse... wenn wir nur einen "In-Container"-LookUp machen wollen müssen wir natürlich nicht PortableRemoteObject.narow(...) aufrufen.

Für interne LookUps könnte man den ServiceLocator beispielsweise so implementieren.
Code:
/*
 * Created on 06.05.2005@20:11:11
 *
 * TODO Add some Licence info
 */
package de.tutorials.ejb.service;

import javax.ejb.EJBLocalHome;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * @author Tom
 * 
 * TODO Describe me
 */
public class ServiceLocator {

    private static InitialContext ctx;

    private static ServiceLocator serviceLocator = new ServiceLocator();

    protected ServiceLocator() {
        try {
            ctx = new InitialContext();
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }

    /**
     * @return Returns the serviceLocator.
     */
    public static ServiceLocator getServiceLocator() {
        return serviceLocator;
    }

    public Object lookup(String jndiName) {
        try {
            return (EJBLocalHome) ctx.lookup(jndiName);
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Damit umgeht man auch das Problem mit der ClassCastException ...Proxy$XY

Gruß Tom
 
Hallo Thomas,
erstmal vielen Dank für das ob. Beispiel, dadurch habe ich nun meine erste EntityBean zum Laufen gebracht.
Nun habe ich vom Internet noch ein andere Beispiel (Ohne local. localHome Descriptoren)probiert.
Leider beim Deployment bekomme ich folgende errors:

12:40:59,017 WARN [verifier] EJB spec violation:
Bean : StudEJB
Method : public abstract Student create(Integer) throws CreateException, RemoteE
xception
Section: 12.2.9
Warning: Each create(...) method in the entity bean's home interface must have a
matching ejbCreate(...) method in the entity bean's class.

Der Code sieht so aus:

public abstract class StudentHome implements EntityBean{
public Integer ejbCreate(Integer MatNr) throws CreateException{
this.setMatrikel(MatNr);
return null;
}
.............
}

public interface StudentHome extends EJBHOME{
public Student create(Integer MatNr) throws
CreateException, RemoteException;
..........
}

Ich weiss nicht, warum es nicht !


Vielen Dank im voraus.

Gruß
Askon
 
hat isch erledigt

Hallo zusammen,

ich habe es rausgefunden. Es lag daran dass im Home "ejbcreate" statt "ejbCreate" stand.:offtopic:

VG,

askon
 
Zurück