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;
}
}
....