Problem mit meinem Bean

ceene

Erfahrenes Mitglied
Ich lerne gerade die Technik mit Beans und Servlets aus dem Buch JBoss von Heiko W. Rupp. Leider ist sein Besipiel ist dem Buch fehlerhaft oder unvollständig.

Ich habe folgendes Bean geschrieben, genau so wie sie im Buch stehen, aber er meckert immer folgende Zeilen an
Code:
private EmailLocalHome elh = null;
private AddressLocalHome alh = null;

das ganze Bean sieht wie folgt aus
Code:
package de.bsd.adb.ejb;

import java.util.*;
import javax.ejb.*;
import javax.naming.*;
import de.bsd.adb.beans.AddrBean;

/*
 * @ejb.bean name="Facade"
 * type="Stateless"
 * view-type="both"
 * jndi-name="adb/Facade"
 * local-jndi-name="adb/FacadeLocal"
 */

public abstract class FacadeSessionBean implements SessionBean {
	
	private EmailLocalHome elh = null;
	private AddressLocalHome alh = null;
	
	public void ejbCreate() throws CreateException	{
		try	
		{
			InitialContext ic = new InitialContext();
			Object o = ic.lookup("adb/Adress");
			alh = (AdressLocalHome) o;
			
			o = ic.lookup("adb/Email");
			elh = (EmailLocalHome) o;
		}
		catch (NamingException e)
		{
			throw new CreateException(e.getMessage());
		}
	}
	
	/*
	 * @ejb.interface-method
	 */
	public AddrBean add(AddrBean a) throws CreateException	{
		if(a==null)
		{
			throw new CreateException("Keine Adresse übergeben");
		}
		
		AdressLocal al;
		ArrayList emailLocals = null;
		//E-Mails in a anlegen
		if(a.getEmail()!=null)
		{
			emailLocals = new ArrayList();
			Iterator it = a.getEmail().iterator();
			//E-mails speichern
			while(it.hasNext())
			{
				String em = (String)it.next();
				EmailLocal el = elh.create(em);
				emailLocals.add(el);
			}
		}
		//Adresse mit E-Mails speichern
		al = alh.create(a,emailLocals);
		return a;
	}
	
	/*
	 * @ejb.interface-method
	 */
	public AddrBean[] suche(String name, String vorname)	{
		AddrBean[] result=null;
		try
		{
			Collection co;
			if(vorname==null || vorname.equals(""))
			{
				co = alh.findByName(name);
			}
			else
			{
				co = alh.findByNameAndVorname(name,vorname);
			}
			
			int size = co.size();
			if(size>0)
			{
				result = new AddrBean[size];
				Iterator it = co.iterator();
				int i = 0;
				while(it.hasNext())
				{
					AddressLocal al = (AdressLocal) it.next();
					result[i] = new AddrBean();
					result[i].setName(al.getName());
					result[i].setVorname(al.getVorname());
					result[i].setStrasse(al.getStrasse());
					result[i].setHausNr(al.getHausNr());
					result[i].setPlz(al.getPlz());
					result[i].setOrt(al.getOrt());
					result[i].setTel(al.getTel());
					
					if(al.getEmails()!=null)
					{
						//EMails auslesen
						ArrayList mails = new ArrayList();
						Iterator eit = al.getEmails().iterator();
						while(eit.hasNext())
						{
							EmailLocal el = (EmailLocal)eit.next();
							String mail = el.getTheEmail();
							mails.add(mail);
						}
						result[i].setEmail(mails);
					}
					i++;
				}
			}
		}
		catch(FinderException e)
		{
			result = null;
		}
		return result;
	}
}

Wie bekomme ich nun die unbekannten typen bekannt? Muss ich da noch ne Bibliothek einbinden?
 
Grundsatzfrage: bist du aus Versehen noch bei Spec 2.1 oder machst du das freiwillig? Mit 3.0 wird das ganze erheblich einfacher. Keine komischen XDoclet Tags, keine hässlichen JNDI Lookups usw. (Soll jetzt keine blöde Anmache sein, sondern einfach nur vermeintlich Offensichtliches hinterfragen. Kann ja sein, dass du aus Zufall an die "veraltete" Version geraten bist.)

Schön, dass du uns mitteilst, welche Zeilen die Fehler hervorrufen. Welche Exception aber genau fliegt, wäre noch interessant ;) Stacktrace usw.

Gruß
Ollie
 
Keine Ahnung auf was du hinaus willst, aber ich verwende alle Versionen wie in meinem Buch.
Mich stört es auch nicht wenn es umständlicher ist als mit anderen Versionen. Ich möchte lediglich den Fehler beheben.

Ich versuche mit build.xml alles zu erzeugen und dabei hört er auf und sagt:
connot find symbol class EmailLocalHome

Das gleich auch bei der anderen Zeile
 
Ich frage mich nur, warum man anfängt sich mit einer älteren Version (in Bezug auf EJB überhaupt - du nutzt EJB in der Version 2.1, aktuell ist aber 3.0) zu beschäftigen, wenn es doch eine aktuellere gibt, die wesentlich einfacher ist. Ich würde mir dann wohl eher das aktuelle Zeug aneignen.

Die Exception ist doch recht eindeutig. Es gibt keine Klasse / kein Interface EmailLocalHome. Macht durchaus Sinn, da dies ja erst vom XDoclet generiert wird.

Gruß
Ollie
 
Ich benutze EJB 2.x weil ich von der ganzen Materie keine Ahnung habe und mir das gerade beibringe. Ich versuche nun ein einfaches Beispiel aus meinem Buch zu machen und wenn das fertig ist und läuft schaue ich mir die einzelnen Komponenten genauer an wie EJB usw. aber leider läuft ja nichtmal das Beispiel aus dem Buch.

Liegt der Fehler dann in der build.xml? Ist da die Reihenfolge eventuell falsch?

build.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." name="adb" default="all">
	<property file="build.properties"/>
	<target name="all" depends="war"/>

	<target name="deploy-war" description="adb.war auf dem Server einspielen">
	<copy overwrite="true"
		file="${build.dir}/adb.war"
		todir="${jboss.deploy.dir}"/>
	</target>
	
	<target name="compile-web" description="Servlet uebersetzen">
		<mkdir dir="${gen-class.dir}"/>
		<javac classpath="${servlet.lib.path}"
			classpathref="server.path.ref"
			debug="on"
			destdir="${gen-class.dir}"
			srcdir="${src.dir}"
			includes="de/bsd/adb/servlets/*.java, de/bsd/adb/beans/*.java"
		/>
	</target>
	
	<target name="war" depends="compile-web" description="adb.war zusammenbauen">
		<war destfile="${build.dir}/adb.war"
		webxml="web.xml">
			<classes dir="${gen-class.dir}">
				<include name="**/servlets/*.class"/>
				<include name="**/beans/*.class"/>
				<include name="**/ejb/Facade.class"/>
				<include name="**/ejb/FacadeHome.class"/>
			</classes>
			<fileset dir="${src.dir}/de/bsd/adb/web">
				<include name="*.jsp"/>
				<include name="*.html"/>
				<include name="prot/*.jsp"/>
			</fileset>
		</war>
	</target>
	
	<path id="xdoclet.path.ref">
		<fileset dir="${xdoclet.lib.path}">
			<include name="*.jar"/>
		</fileset>
		<fileset dir="${jboss.client.dir}">
			<include name="jboss-j2ee.jar"/>
		</fileset>
	</path>
	
	<path id="server.path.ref">
		<pathelement location ="${build.dir}/adb-ejb.jar"/>
		<pathelement location = "%{jboss.client.dir}/jboss-j2ee.jar"/>
	</path>
	
	<target name="init">
		<taskdef name="ejbdoclet"
			classname="xdoclet.modules.ejb.EjbDocletTask"
			classpathref="xdoclet.path.ref"/>
		<mkdir dir="build"/>
		<mkdir dir="build/gen-classes"/>
		<mkdir dir="META-INF"/>
	</target>
	
	<target name="ejbdoclet"
	depends = "init"
	description="Hilfsklassen für EJBs erzeugen">
		<ejbdoclet destdir="${gen-src.dir}"
		ejbspec="2.1">
			<fileset dir="${src.dir}">
				<include name="de/bsd/adb/ejb/*.java"/>
			</fileset>
			<localinterface/>
			<localhomeinterface/>
			<remoteinterface/>
			<homeinterface/>
			<entitypk/>
			<entitycmp/>
			<session/>
			<deploymentdescriptor
			destdir="${build.dir}/META-INF"
			validatexml="true"/>
			<jboss destdir="${build.dir}/META-INF"
			version="4.0"/>
		</ejbdoclet>
	</target>
	
	<target name="compile-ejb"
	description="EJBs übersetzen"
	depends="ejbdoclet">
		<mkdir dir="${gen-class.dir}"/>
		<javac classpath="${j2ee.lib}"
		debug="on"
		destdir="${gen-class.dir}"
		includes="de/bsd/adb/ejb/*.java, de/bsd/adb/beans/*.java">
			<src path="${src.dir}"/>
			<srv path="${gen-src.dir}"/>
		</javac>
	</target>
	
	<target name="jar"
	description="build adb-ejb.jar"
	depends="compile-ejb">
		<jar destfile="${build.dir}/adb-ejb.jar">
			<fileset dir="${gen-class.dir}">
				<include name="de/bsd/adb/ejb/*.class"/>
				<include name="de/bsd/adb/beans/*.class"/>
			</fileset>
			<metainf dir="${build.dir]/META-INF"/>
		</jar>
	</target>
	
	<target name="ear"
	description="Baut adb-app.ear"
	depends="war,jar">
		<ear destfile="${build.dir}/adb-app.ear"
		appxml="application.xml2">
			<fileset dir="${build.dir}"
				includes="*.jar,*.war"/>
		</ear>
	</target>
</project>
 
Zuletzt bearbeitet:
Puh, wenn man sowas liest, lernt man Maven wieder zu schätzen ;). Soweit ich das verfolgen konnte, wir das XDoclet target im normalen Durchlauf gar nicht angestoßen, oder? Das Target "all" baut komischerweise scheinbar nur den Webteil zusammen (kann aber auch sein, dass ich beim Hindurchwühlen was übersehen hab).

Grundsätzlich solltest du erst den Serverteil (XDoclet verarbeiten, kompilieren, EAR File bauen) und danach den Webteil bauen.

Gruß
Ollie
 
Also ich habe nun alles in der richtigen Reihenfolge, aber es kommen noch immer die gleichen Fehler.

Es kann ja auch nicht sein, dass in Eclipse die Teile unterstrichen werden, dann aber trotzdem gehen sollen.
Ich denke mal solange die unterstrichen sind, stimmt da was nicht. Leider kann ich nicht sagen was, da das für mich neu ist.

Ich habe folgende Dateien, in denen ein Fehler auftritt
WorkerServlet.java
Hier werden die beiden Zeilen angekreidet
private FacadeHome fh = null;
private Facade fa = null;
Code:
package de.bsd.adb.servlets;

import java.io.IOException;
import java.util.*;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.naming.*;

import de.bsd.adb.beans.*;
import de.bsd.adb.ejb.FacadeSessionBean;

public class WorkerServlet extends HttpServlet {

	private final static int SEARCH = 0;
	private final static int ADD = 1;
	private String targetPage = "/index.jsp";
	private FacadeHome fh = null;
	private Facade fa = null;
	
	public void init() throws ServletException	{
		try
		{
			InitialContext ic = new InitialContext();
			Object o = ic.lookup("adb/Facade");
			fh = (FacadeHome) o;
		}
		catch(NamingException e)
		{
			fh = null;
			throw new ServletException(e);
		}
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse resp)	
	throws ServletException, IOException	{
		String tasks = req.getParameter("task");
		int task;
		if("add".equals(tasks))
		{
			task=ADD;
		}
		else if("search".equals(tasks))
		{
			task=SEARCH;
		}
		else
		{
			resp.sendError(HttpServletResponse.SC_EXPECTATION_FAILED, "bad request");
			return;
		}
		AddrBean[] addrs = null;
		switch(task)	{
			case ADD:
				addrs = handleAdd(req);
				break;
			case SEARCH:
				addrs = handleSearch(req);
				break;
		}
		HttpSession session = req.getSession(true);
		session.setAttribute("addrs",addrs);
		
		RequestDispatcher rd = req.getRequestDispatcher(targetPage);
		rd.forward(req, resp);
	}
	
	private AddrBean[] handleSearch(HttpServletRequest req){
		AddrBean[] result = null;
		String name=req.getParameter("name");
		try
		{
			Facade fa = fh.create();
			result = fa.suche(name,null);
			fa.remove();
		}
		catch (Exception e)
		{
			result = null;
		}
		targetPage = "/index.jsp";
		return result;
	}
	
	private AddrBean[] handleAdd(HttpServletRequest req)	{
		AddrBean a = new AddrBean();
		AddrBean[] result = new AddrBean[1];
		ArrayList mails = new ArrayList();
		mails.add(req.getParameter("email"));
		mails.add(req.getParameter("email2"));

		a.setEmail(mails);
		a.setName(req.getParameter("name"));
		a.setOrt(req.getParameter("ort"));
		a.setPlz(req.getParameter("plz"));
		a.setStrasse(req.getParameter("strasse"));
		a.setTel(req.getParameter("tel"));
		a.setVorname(req.getParameter("vorname"));
		
		try
		{
			Facade fa = fh.create();
			fa.add(a);
			fa.remove();
			result[0]=a;
		}
		catch (Exception e)
		{
			result = null;
		}
		
		targetPage = "/index.jsp";
		return result;
	}
}

FacadeSessionBean.java
Hier werden die beiden Zeilen angekreidet
private EmailLocalHome elh = null;
private AddressLocalHome alh = null;
Code:
package de.bsd.adb.ejb;

import java.util.*;
import javax.ejb.*;
import javax.naming.*;
import de.bsd.adb.beans.AddrBean;

/**
 * @ejb.bean name="Facade"
 * type="Stateless"
 * view-type="both"
 * jndi-name="adb/Facade"
 * local-jndi-name="adb/FacadeLocal"
 */

public abstract class FacadeSessionBean implements SessionBean {
	
	private EmailLocalHome elh = null;
	private AddressLocalHome alh = null;
	
	public void ejbCreate() throws CreateException	{
		try	
		{
			InitialContext ic = new InitialContext();
			Object o = ic.lookup("adb/Adress");
			alh = (AdressLocalHome) o;
			
			o = ic.lookup("adb/Email");
			elh = (EmailLocalHome) o;
		}
		catch (NamingException e)
		{
			throw new CreateException(e.getMessage());
		}
	}
	
	/**
	 * @ejb.interface-method
	 */
	public AddrBean add(AddrBean a) throws CreateException	{
		if(a==null)
		{
			throw new CreateException("Keine Adresse übergeben");
		}
		
		AdressLocal al;
		ArrayList emailLocals = null;
		//E-Mails in a anlegen
		if(a.getEmail()!=null)
		{
			emailLocals = new ArrayList();
			Iterator it = a.getEmail().iterator();
			//E-mails speichern
			while(it.hasNext())
			{
				String em = (String)it.next();
				EmailLocal el = elh.create(em);
				emailLocals.add(el);
			}
		}
		//Adresse mit E-Mails speichern
		al = alh.create(a,emailLocals);
		return a;
	}
	
	/**
	 * @ejb.interface-method
	 */
	public AddrBean[] suche(String name, String vorname)	{
		AddrBean[] result=null;
		try
		{
			Collection co;
			if(vorname==null || vorname.equals(""))
			{
				co = alh.findByName(name);
			}
			else
			{
				co = alh.findByNameAndVorname(name,vorname);
			}
			
			int size = co.size();
			if(size>0)
			{
				result = new AddrBean[size];
				Iterator it = co.iterator();
				int i = 0;
				while(it.hasNext())
				{
					AddressLocal al = (AdressLocal) it.next();
					result[i] = new AddrBean();
					result[i].setName(al.getName());
					result[i].setVorname(al.getVorname());
					result[i].setStrasse(al.getStrasse());
					result[i].setHausNr(al.getHausNr());
					result[i].setPlz(al.getPlz());
					result[i].setOrt(al.getOrt());
					result[i].setTel(al.getTel());
					
					if(al.getEmails()!=null)
					{
						//EMails auslesen
						ArrayList mails = new ArrayList();
						Iterator eit = al.getEmails().iterator();
						while(eit.hasNext())
						{
							EmailLocal el = (EmailLocal)eit.next();
							String mail = el.getTheEmail();
							mails.add(mail);
						}
						result[i].setEmail(mails);
					}
					i++;
				}
			}
		}
		catch(FinderException e)
		{
			result = null;
		}
		return result;
	}
}

Meine build.xml sieht mittlerweile so aus
Code:
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." name="adb" default="all">
	<property file="build.properties"/>
	<target name="all" depends="war"/>
	
	
	<path id="xdoclet.path.ref">
				<fileset dir="${xdoclet.lib.path}">
					<include name="*.jar"/>
				</fileset>
				<fileset dir="${jboss.client.dir}">
					<include name="jboss-j2ee.jar"/>
				</fileset>
			</path>
			
			<path id="server.path.ref">
				<pathelement location ="${build.dir}/adb-ejb.jar"/>
				<pathelement location = "${jboss.client.dir}/jboss-j2ee.jar"/>
			</path>
			
	<target name="init">
								<taskdef name="ejbdoclet"
									classname="xdoclet.modules.ejb.EjbDocletTask"
									classpathref="xdoclet.path.ref"/>
								<mkdir dir="build"/>
								<mkdir dir="build/gen-classes"/>
								<mkdir dir="META-INF"/>
							</target>	
			<target name="ejbdoclet"
			depends = "init"
			description="Hilfsklassen für EJBs erzeugen">
				<ejbdoclet destdir="${gen-src.dir}"
				ejbspec="2.1">
					<fileset dir="${src.dir}">
						<include name="de/bsd/adb/ejb/*.java"/>
					</fileset>
					<localinterface/>
					<localhomeinterface/>
					<remoteinterface/>
					<homeinterface/>
					<entitypk/>
					<entitycmp/>
					<session/>
					<deploymentdescriptor
					destdir="${build.dir}/META-INF"
					validatexml="true"/>
					<jboss destdir="${build.dir}/META-INF"
					version="4.0"/>
				</ejbdoclet>
			</target>
			
			<target name="compile-ejb"
			description="EJBs übersetzen"
			depends="ejbdoclet">
				<mkdir dir="${gen-class.dir}"/>
				<javac classpath="${j2ee.lib}"
				debug="on"
				destdir="${gen-class.dir}"
				includes="de/bsd/adb/ejb/*.java, de/bsd/adb/beans/*.java">
					<src path="${src.dir}"/>
					<srv path="${gen-src.dir}"/>
				</javac>
			</target>
			
			<target name="jar"
			description="build adb-ejb.jar"
			depends="compile-ejb">
				<jar destfile="${build.dir}/adb-ejb.jar">
					<fileset dir="${gen-class.dir}">
						<include name="de/bsd/adb/ejb/*.class"/>
						<include name="de/bsd/adb/beans/*.class"/>
					</fileset>
					<metainf dir="${build.dir]/META-INF"/>
				</jar>
			</target>
	
	
	
	<target name="war" depends="compile-web" description="adb.war zusammenbauen">
		<war destfile="${build.dir}/adb.war"
		webxml="web.xml">
			<classes dir="${gen-class.dir}">
				<include name="**/ejb/Facade.class"/>
				<include name="**/ejb/FacadeHome.class"/>
				<include name="**/servlets/*.class"/>
				<include name="**/beans/*.class"/>
			</classes>
			<fileset dir="${src.dir}/de/bsd/adb/web">
				<include name="*.jsp"/>
				<include name="*.html"/>
				<include name="prot/*.jsp"/>
			</fileset>
		</war>
	</target>
	<target name="ear"
				description="Baut adb-app.ear"
				depends="war,jar">
					<ear destfile="${build.dir}/adb-app.ear"
					appxml="application.xml2">
						<fileset dir="${build.dir}"
							includes="*.jar,*.war"/>
					</ear>
				</target>
	<target name="compile-web" description="Servlet uebersetzen">
			<mkdir dir="${gen-class.dir}"/>
			<javac classpath="${servlet.lib.path}"
				classpathref="server.path.ref"
				debug="on"
				destdir="${gen-class.dir}"
				srcdir="${src.dir}"
				includes="de/bsd/adb/servlets/*.java, de/bsd/adb/beans/*.java"
			/>
		</target>
	<target name="deploy-war" description="adb.war auf dem Server einspielen">
		<copy overwrite="true"
			file="${build.dir}/adb.war"
			todir="${jboss.deploy.dir}"/>
		</target>
</project>

Da dieses Thema für mich absolut neu ist (ich arbeite mich in das Thema gerade erst ein und habe 0Erfahrung) wäre es toll wenn mir jemand sagen könnte wo das Problem liegt.
Fehlt eine Bibliothek oder eine andere Datei oder wie kommen die Fehler zustande?
 
Wie das Problem zu stande kommt, habe ich dir doch schon erklärt. Die fehlenden Home Interfaces werden mit XDoclet generiert. Bevor das nicht geschehen ist, liegen die nicht im Classpath und Eclipse schimpft.

Wenn man in Eclipse ein externes Buildsystem (in deinem Fall Ant) benutzt kommt es gern mal zu solchen "Fehlern". Das sollte allerdings zu beheben sein, in dem du das Buildskript einmal startest, was dir dann eigentlich die entsprechenden Interfaces generieren sollte.

Die Fehlerquelle lässt sich also auf 2 Punkt eingrenzen: Entweder tut dein target ejbdoclet nicht genau das was es soll (spuckt das buildlog evtl warnings oder sowas aus?) oder das target funktioniert und eclipse schnallt nicht, dass da dateien neu generiert wurden. In letzterem Fall schaft ein Refresh auf dem Projekt oder ein Project -> Clean oft Abhilfe.

Gruß
Ollie
 
in meinem build.xml in Eclipse ist bei taskdef name=ejbdoclet eine Warnung

"C:\c\ejb30\jboss-4.0.4.ga\client not found"

in der entsprechenden Variable habe ich folgendes stehen:
"/c/xdoclet/lib"

Allerdings verstehe ich nicht warum er da nichts findet
der Pfad bei der Variable jboss.dir ist auch in dem Format angegeben und er findet es ohne Probleme.

Kann es daran liegen?
 

Neue Beiträge

Zurück