# Deployen einer EJB3.0 Bean



## nagash56 (13. Okt 2005)

Hi, ich versuch grad mein Glück daran eine Stateless Session Bean zu deployen. Ich verwende JBoss 4.0.3

Folgende Bean soll deployed werden:

Interface:

```
package umit.swpg.server.ejb;

public interface Calculator {
	public double calculate(double first, double second);
}
```

Bean:

```
package umit.swpg.server.ejb;

@Stateless
public class CalculatorBean implements Calculator {

	public double calculate(double first, double second) {
		return first + second;
	}
	
}
```

Die Bean soll dann in einem Servlet (zu Testzwecken) aufgerufen werden:


```
public class Login extends HttpServlet {
	public void doGet(HttpServletRequest rq, HttpServletResponse rs)
	                                                   throws IOException, ServletException {
		rs.getWriter().write("<H1>Hallo</H1>");
		Calculator cal = null;
		try {
			InitialContext ctx = new InitialContext();
			cal = (Calculator) ctx.lookup(
			                  Calculator.class.getName());
		} catch (Exception e) {
		       e.printStackTrace ();
		}
		rs.getWriter().write("<H1>" + cal.calculate(3, 3) + "<H1>");
	}
}
```

Ich verpack dann die Webapplikation und die EJB in eine ear und ich schätz das funktioniert auch.
EAR - Struktur:
- META-INF
  -- application.xml
- business.ejb3
- marfan.war

Das Servlet kann ich ohne Probleme aufrufen allerdings bekomme ich eine Nullpointerexception beim Lookup der Bean mit der Exception: javax.naming.NameNotFoundException: umit.swpg.server.ejb.Calculator not bound

Das kann jetzt wahrscheinlich alles mögliche sein. Im konkreten hab ich nur eine Frage. Ich kompiliere die EJB in Eclipse mit JDK1.5. Die annotation @Stateless wird allerdings rot unterwellt mit der Meldung: "Stateless cannot be resolved to a type". Jetzt kenn ich mich nicht wirklich aus wie der Compiler solche Annotations handhabt. Muss ich irgendeine Bibliothek importieren damit er beim Compilieren die Annotation richtig compiliert und somit die EJB erst richtig deployed werden kann oder ist das egal und das kann nicht der Grund für den Fehler sein?


----------



## Bleiglanz (14. Okt 2005)

lies die deploymeldungen in der jboss konsole

und:

die Annotation ist eine stinknormale Java Klasse, du musst die entsprechende Bibliothek im Build-Path haben

und du brauchst sie natürlich, weil der Server das entsprechende class-File analysiert und nur bei vorhandensein eine SessionBean daraus macht!


----------



## nagash56 (14. Okt 2005)

Ich hab die Klasse javax.ejb.Stateless jetzt importiert. Funktioniert auch soweit. Bei start up sagt mir der [EARDeployer], dass die J2EE applikation test.ear initialisiert und gestartet wird, ebenso die webapplikation

Ausschnitt aus der JBoss Console:

16:56:42,944 INFO  [ConnectionFactoryBindingService] Bound ConnectionManager 'jb
oss.jca:service=DataSourceBinding,name=DefaultDS' to JNDI name 'javaefaultDS'
16:56:43,404 INFO  [A] Bound to JNDI name: queue/A
16:56:43,414 INFO  * Bound to JNDI name: queue/B
16:56:43,414 INFO  
	
	
	
	






		Code:In die Zwischenablage kopieren


 Bound to JNDI name: queue/C
16:56:43,424 INFO  [D] Bound to JNDI name: queue/D
16:56:43,424 INFO  [ex] Bound to JNDI name: queue/ex
16:56:43,464 INFO  [testTopic] Bound to JNDI name: topic/testTopic
16:56:43,464 INFO  [securedTopic] Bound to JNDI name: topic/securedTopic
16:56:43,475 INFO  [testDurableTopic] Bound to JNDI name: topic/testDurableTopic

16:56:43,475 INFO  [testQueue] Bound to JNDI name: queue/testQueue
16:56:43,585 INFO  [UILServerILService] JBossMQ UIL service available at : /0.0.
0.0:8093
16:56:43,655 INFO  [DLQ] Bound to JNDI name: queue/DLQ
16:56:44,356 INFO  [ConnectionFactoryBindingService] Bound ConnectionManager 'jb
oss.jca:service=ConnectionFactoryBinding,name=JmsXA' to JNDI name 'java:JmsXA'
16:56:44,486 INFO  [TomcatDeployer] deploy, ctxPath=/jmx-console, warUrl=.../dep
loy/jmx-console.war/
16:56:44,887 INFO  [EARDeployer] Init J2EE application: file:/D:/jboss-4.0.3/ser
ver/all/deploy/Test.ear
16:56:45,648 INFO  [TomcatDeployer] deploy, ctxPath=/Marfan, warUrl=.../tmp/depl
oy/tmp5570Test.ear-contents/Marfan-exp.war/
16:56:45,828 INFO  [EARDeployer] Started J2EE application: file:/D:/jboss-4.0.3/
server/all/deploy/Test.ear
16:56:46,279 INFO  [Http11Protocol] Starting Coyote HTTP/1.1 on http-0.0.0.0-808
0
16:56:46,509 INFO  [ChannelSocket] JK: ajp13 listening on /0.0.0.0:8009
16:56:46,549 INFO  [JkMain] Jk running ID=0 time=0/100  config=null
16:56:46,569 INFO  [Server] JBoss (MX MicroKernel) [4.0.3 (build: CVSTag=JBoss_4
_0_3 date=200510042324)] Started in 37s:133ms
16:59:50,043 INFO  [STDOUT] javax.naming.NameNotFoundException: umit.swpg.server
.ejb.Calculator not bound
16:59:50,043 INFO  [STDOUT]     at org.jnp.server.NamingServer.getBinding(Naming
Server.java:514)
16:59:50,043 INFO  [STDOUT]     at org.jnp.server.NamingServer.getBinding(Naming
Server.java:522)
16:59:50,043 INFO  [STDOUT]     at org.jnp.server.NamingServer.getObject(NamingS
erver.java:528)
16:59:50,043 INFO  [STDOUT]     at org.jnp.server.NamingServer.lookup(NamingServ
er.java:281)
16:59:50,043 INFO  [STDOUT]     at org.jnp.interfaces.NamingContext.lookup(Namin
gContext.java:610)
16:59:50,043 INFO  [STDOUT]     at org.jnp.interfaces.NamingContext.lookup(Namin
gContext.java:572)
16:59:50,053 INFO  [STDOUT]     at javax.naming.InitialContext.lookup(InitialCon
text.java:351)
16:59:50,053 INFO  [STDOUT]     at umit.swpg.server.logic.Login.doGet(Login.java
:34)
16:59:50,053 INFO  [STDOUT]     at javax.servlet.http.HttpServlet.service(HttpSe
rvlet.java:697)
16:59:50,053 INFO  [STDOUT]     at javax.servlet.http.HttpServlet.service(HttpSe
rvlet.java:810)


Wenn irgendjemand noch einen Tipp hat wäre ich dankbar. Kann es sein, dass ich JNDI irgendwie konfigurieren muss damit das funktioniert?

*


----------



## Bleiglanz (15. Okt 2005)

beim lookup vielleicht

CalculatorBean.class.getName());


----------



## nagash56 (15. Okt 2005)

Mittlerweile bin ich ein wenig weiter gekommen. Ich glaub das Problem war, dass bei meinem JBoss nicht alle nötigen Dinge für ein einwandfreies EJB3 Deployment dabei waren, deswegen hab ich das EJB3 Package downgeloaded und installiert. Beim Startup kommen jetzt ein wenig mehr (erfreuliche) Meldungen:

------------- Ausschnitt start up -----------------------------
17:56:31,666 INFO  [ConnectionFactoryBindingService] Bound ConnectionManager 'jb
oss.jca:service=DataSourceBinding,name=DefaultDS' to JNDI name 'javaefaultDS'
17:56:32,717 INFO  [A] Bound to JNDI name: queue/A
17:56:32,717 INFO  * Bound to JNDI name: queue/B
17:56:32,717 INFO  
	
	
	
	






		Code:In die Zwischenablage kopieren


 Bound to JNDI name: queue/C
17:56:32,727 INFO  [D] Bound to JNDI name: queue/D
17:56:32,727 INFO  [ex] Bound to JNDI name: queue/ex
17:56:32,757 INFO  [testTopic] Bound to JNDI name: topic/testTopic
17:56:32,757 INFO  [securedTopic] Bound to JNDI name: topic/securedTopic
17:56:32,757 INFO  [testDurableTopic] Bound to JNDI name: topic/testDurableTopic

17:56:32,767 INFO  [testQueue] Bound to JNDI name: queue/testQueue
17:56:32,917 INFO  [UILServerILService] JBossMQ UIL service available at : /0.0.
0.0:8093
17:56:32,978 INFO  [DLQ] Bound to JNDI name: queue/DLQ
17:56:33,298 INFO  [ConnectionFactoryBindingService] Bound ConnectionManager 'jb
oss.jca:service=ConnectionFactoryBinding,name=JmsXA' to JNDI name 'java:JmsXA'
17:56:33,358 INFO  [TomcatDeployer] deploy, ctxPath=/jmx-console, warUrl=.../dep
loy/jmx-console.war/
17:56:33,608 INFO  [EARDeployer] Init J2EE application: file:/D:/jbossEJB3/serve
r/all/deploy/Test.ear
17:56:33,989 INFO  [JaccHelper] Initialising JACC Context for deployment: busine
ss.ejb3
17:56:34,269 INFO  [Ejb3AnnotationHandler] found EJB3: ejbName=server.ejb.Calcul
atorBean, class=server.ejb.CalculatorBean, type=STATELESS
17:56:34,650 INFO  [JaccHelper] server.ejb.CalculatorBean has no @SecurityDomain
 - skipping JACC configuration
17:56:34,650 INFO  [JaccHelper] JACC Policy Configuration for deployment has bee
n put in service
17:56:34,650 INFO  [Ejb3Deployment] EJB3 deployment time took: 661
17:56:34,840 INFO  [ProxyDeployer] no declared remote bindings for : server.ejb.
CalculatorBean
17:56:34,840 INFO  [ProxyDeployer] there is remote interfaces for server.ejb.Cal
culatorBean
17:56:34,850 INFO  [ProxyDeployer] default remote binding has jndiName of server
.ejb.RemoteCalculator
17:56:35,010 INFO  [EJB3Deployer] Deployed: file:/D:/jbossEJB3/server/all/tmp/de
ploy/tmp20642Test.ear-contents/business.ejb3
17:56:35,020 INFO  [TomcatDeployer] deploy, ctxPath=/Marfan, warUrl=.../tmp/depl
oy/tmp20642Test.ear-contents/Marfan-exp.war/
17:56:35,151 INFO  [EARDeployer] Started J2EE application: file:/D:/jbossEJB3/se
rver/all/deploy/Test.ear
17:56:35,601 INFO  [Http11Protocol] Starting Coyote HTTP/1.1 on http-0.0.0.0-808
0
17:56:35,812 INFO  [ChannelSocket] JK: ajp13 listening on /0.0.0.0:8009
17:56:35,842 INFO  [JkMain] Jk running ID=0 time=0/60  config=null
17:56:35,852 INFO  [Server] JBoss (MX MicroKernel) [4.0.3 (build: CVSTag=JBoss_4
_0_3 date=200510042324)] Started in 47s:238ms

Die Klassen schauen konkret jetzt wie folgt aus:
[code]
package server.ejb;
// Local interface in Calculator.class
public interface Calculator {
	public double calculate(double one, double two);
}

package server.ejb;
// Remote interface in RemoteCalculator.class
public interface RemoteCalculator {
	public double calculate(double one, double two);
}

package server.ejb;

import javax.ejb.*;
// Die EJB in CalculatorBean.class
@Stateless
@Local ({Calculator.class})
@Remote ({RemoteCalculator.class})
public class CalculatorBean implements Calculator, RemoteCalculator {
	public double calculate(double one, double two) {
		return one + two;
	}
}

Wenn ich jetzt im Servlet den Lookup mache dann scheint es so zu sein als findet er einen Stub, allerdings kann das Object nicht in das gewünschte Interface gecastet werden:


		Code:In die Zwischenablage kopieren


package umit.swpg.server.logic;

import java.io.IOException;
import javax.naming.InitialContext;
import javax.servlet.*;
import javax.servlet.http.*;
import server.ejb.Calculator;
import server.ejb.RemoteCalculator;

public class Login extends HttpServlet {
	public void doGet(HttpServletRequest rq, HttpServletResponse rs)
	                              throws ServletException, IOException {
		rs.getWriter().write("<H1>Hallo</H1>");
		Calculator cal = null;
		RemoteCalculator remoteCal = null;
		try {
			InitialContext ctx = new InitialContext();
                           // Hier passiert die ClassCastException
			remoteCal = (RemoteCalculator) ctx.lookup(RemoteCalculator.class.getName()); 
			rs.getWriter().write("<H1>" + remoteCal.calculate(1, 3) + "</H1>");
		}
		catch (Exception e) {
			rs.getWriter().write("<H1>" + e.getMessage() + "<H1>");   
			e.printStackTrace ();
		}
	}
}

17:57:11,313 INFO  [STDOUT] java.lang.ClassCastException: $Proxy66
17:57:11,313 INFO  [STDOUT]     at umit.swpg.server.logic.Login.doGet(Login.java
:29)
17:57:11,313 INFO  [STDOUT]     at javax.servlet.http.HttpServlet.service(HttpSe
rvlet.java:697)
17:57:11,313 INFO  [STDOUT]     at javax.servlet.http.HttpServlet.service(HttpSe
rvlet.java:810)
17:57:11,313 INFO  [STDOUT]     at org.apache.catalina.core.ApplicationFilterCha
in.internalDoFilter(ApplicationFilterChain.java:252)
17:57:11,313 INFO  [STDOUT]     at org.apache.catalina.core.ApplicationFilterCha
in.doFilter(ApplicationFilterChain.java:173)
17:57:11,313 INFO  [STDOUT]     at org.jboss.web.tomcat.filters.ReplyHeaderFilte
r.doFilter(ReplyHeaderFilter.java:81)
17:57:11,313 INFO  [STDOUT]     at org.apache.catalina.core.ApplicationFilterCha
in.internalDoFilter(ApplicationFilterChain.java:202)
17:57:11,313 INFO  [STDOUT]     at org.apache.catalina.core.ApplicationFilterCha
i

Wenn ich statt dem RemoteInterface das LocalInterface verwende passiert dasselbe. Ich habe auch versucht das lookup mit CalculatorBean.class.getName() zu machen, aber dann kommt wieder eine NameNotBoundException.
Dann hab ich mir gedacht ich lass das mit der EJB3.0 Spezifikation und probiers mal nach der alten Variante mit Deployment descriptoren etc.
Folgende Klassen habe ich verwendet:


		Code:In die Zwischenablage kopieren


package bonus.calculation;

import javax.ejb.EJBObject;
import java.rmi.RemoteException;

public interface BonusCalculator extends EJBObject {
	public double calculateBonus(int multiplier, double bonus)
                     						throws RemoteException;
}




		Code:In die Zwischenablage kopieren


package bonus.calculation;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;

public interface BonusCalculatorHome extends EJBHome {
	BonusCalculator create() throws CreateException, RemoteException;
}




		Code:In die Zwischenablage kopieren


package bonus.calculation;

import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

public class BonusCalculatorBean implements SessionBean {
	
	public double calculateBonus(int multiplier, double bonus) {
		double calculatedBonus = (multiplier * bonus);
		return calculatedBonus;
	}

	public void ejbCreate(){}
	public void setSessionContext(SessionContext ctx) {}
	public void ejbRemove() {}
	public void ejbActivate() {}
	public void ejbPassivate() {}
	public void ejbLoad() {}
	public void ejbStore() {}
}


Wenn ich im Servlet dann versuche die Bean aufrufe bekomme ich wieder eine ClassCastException an der gleichen Stelle:



		Code:In die Zwischenablage kopieren


package umit.swpg.server.logic;

import java.io.IOException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import javax.servlet.*;
import javax.servlet.http.*;

import bonus.calculation.BonusCalculator;
import bonus.calculation.BonusCalculatorHome;

public class Login extends HttpServlet {
	public void doGet(HttpServletRequest rq, HttpServletResponse rs)
	                              throws IOException, ServletException {
		rs.getWriter().write("<H1>Hallo</H1>");
		try {
			InitialContext initial = new InitialContext();
			Context myEnv = (Context) initial.lookup("java:comp/env");
			Object ref = myEnv.lookup("ejb/BonusCalculator");
                          // Hier passiert die ClassCastException
                          BonusCalculatorHome home = (BonusCalculatorHome)
	                         PortableRemoteObject.narrow(ref, BonusCalculatorHome.class);
                           rs.getWriter().write("<H1>Homeinterface geholt<H1>");
                           BonusCalculator reserve = home.create();
	                  rs.getWriter().write("<H1>" + reserve.calculateBonus(3, 2)+ "<H1>");
		} 
                  catch (Exception e) {
			e.printStackTrace ();
		}
	}
}


----- Ausschnitt JBossConsole ------------
18:11:32,551 INFO  [testQueue] Bound to JNDI name: queue/testQueue
18:11:32,651 INFO  [UILServerILService] JBossMQ UIL service available at : /0.0.
0.0:8093
18:11:32,741 INFO  [DLQ] Bound to JNDI name: queue/DLQ
18:11:32,962 INFO  [ConnectionFactoryBindingService] Bound ConnectionManager 'jb
oss.jca:service=ConnectionFactoryBinding,name=JmsXA' to JNDI name 'java:JmsXA'
18:11:33,032 INFO  [TomcatDeployer] deploy, ctxPath=/jmx-console, warUrl=.../dep
loy/jmx-console.war/
18:11:33,192 INFO  [EARDeployer] Init J2EE application: file:/D:/jboss-4.0.3/ser
ver/default/deploy/Test.ear
18:11:33,603 INFO  [EjbModule] Deploying BonusCalculator
18:11:33,803 INFO  [ProxyFactory] Bound EJB Home 'BonusCalculator' to jndi 'Bonu
sCalculator'
18:11:33,803 INFO  [EJBDeployer] Deployed: file:/D:/jboss-4.0.3/server/default/t
mp/deploy/tmp23536Test.ear-contents/ejb.jar
18:11:33,863 INFO  [TomcatDeployer] deploy, ctxPath=/Marfan, warUrl=.../tmp/depl
oy/tmp23536Test.ear-contents/Marfan-exp.war/
18:11:34,013 INFO  [EARDeployer] Started J2EE application: file:/D:/jboss-4.0.3/
server/default/deploy/Test.ear
18:11:34,253 INFO  [Http11Protocol] Starting Coyote HTTP/1.1 on http-0.0.0.0-808
0
18:11:34,494 INFO  [ChannelSocket] JK: ajp13 listening on /0.0.0.0:8009
18:11:34,514 INFO  [JkMain] Jk running ID=0 time=0/100  config=null
18:11:34,524 INFO  [Server] JBoss (MX MicroKernel) [4.0.3 (build: CVSTag=JBoss_4
_0_3 date=200510042324)] Started in 20s:840ms
18:11:52,980 INFO  [STDOUT] java.lang.ClassCastException
18:11:52,980 INFO  [STDOUT]     at com.sun.corba.se.impl.javax.rmi.PortableRemot
eObject.narrow(PortableRemoteObject.java:229)
18:11:52,980 INFO  [STDOUT]     at javax.rmi.PortableRemoteObject.narrow(Portabl
eRemoteObject.java:137)
18:11:52,980 INFO  [STDOUT]     at umit.swpg.server.logic.Login.doGet(Login.java
:39)
18:11:52,980 INFO  [STDOUT]     at javax.servlet.http.HttpServlet.service(HttpSe
rvlet.java:697)
18:11:52,980 INFO  [STDOUT]     at javax.servlet.http.HttpServlet.service(HttpSe
rvlet.java:810)
18:11:52,980 INFO  [STDOUT]     at org.apache.catalina.core.ApplicationFilterCha
in.internalDoFilter(ApplicationFilterChain.java:252)
18:11:52,980 INFO  [STDOUT]     at org.apache.catalina.core.ApplicationFilterCha
in.doFilter(ApplicationFilterChain.java:173)
18:11:52,980 INFO  [STDOUT]     at org.jboss.web.tomcat.filters.ReplyHeaderFilte
r.doFilter(ReplyHeaderFilter.java:81)
18:11:52,980 INFO  [STDOUT]     at org.apache.catalina.core.ApplicationFilterCha
in.internalDoFilter(ApplicationFilterChain.java:202)

Deployment der Bean und des Servlets:


		Code:In die Zwischenablage kopieren


<?xml version="1.0"?>

<!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN' 
   'http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd'>

<ejb-jar>
   <enterprise-beans>
      
      <session>
         <description>EJB Test</description>
         <ejb-name>BonusCalculator</ejb-name>.
         <home>bonus.calculation.BonusCalculatorHome</home>
         <remote>bonus.calculation.BonusCalculator</remote>
         <ejb-class>bonus.calculation.BonusCalculatorBean</ejb-class>
         
         <session-type>Stateless</session-type>
         <transaction-type>Container</transaction-type>
      </session>
   </enterprise-beans>
   <assembly-descriptor></assembly-descriptor>
</ejb-jar>




		Code:In die Zwischenablage kopieren


<?xml version="1.0" encoding="ISO-8859-1" ?> 

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
      http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 
    version="2.4"> 

    
    <servlet>
        <servlet-name>Login</servlet-name>
        <servlet-class>umit.swpg.server.logic.Login</servlet-class>
    </servlet>	
    <servlet-mapping>
        <servlet-name>Login</servlet-name>
        <url-pattern>/servlet/Login</url-pattern>
    </servlet-mapping> 

    <ejb-ref>
        <ejb-ref-name>ejb/BonusCalculator</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        <home>bonus.calculation.BonusCalculatorHome</home>
        <remote>bonus.calculation.BonusCalculatorr</remote>
	<ejb-link>BonusCalculator</ejb-link>
    </ejb-ref>

    
</web-app>


Offensichtlich bin ich nicht in der Lage eine einfache EJB zum laufen zu bringen :-(*


----------

