[EJB3] - How to configure EJB3 MDBs for IBM Websphere MQ
by Administrator Administrator
Administrator Administrator [http://community.jboss.org/people/admin] modified the document:
"How to configure EJB3 MDBs for IBM Websphere MQ"
To view the document, visit: http://community.jboss.org/docs/DOC-12944
--------------------------------------------------------------
You do not need deployment descriptors for ejb3. The perferred method for configuring EJB3s would be with the annotations.
This is how you would define your ejb3 bean with all of the properties.
@MessageDriven( name="MyMDBName",
activationConfig =
{
@ActivationConfigProperty(propertyName="messagingType",propertyValue="javax.jms.MessageListener"),
@ActivationConfigProperty(propertyName = "destinationType",propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "queueA"),
@ActivationConfigProperty(propertyName = "useJNDI", propertyValue = "true"),
@ActivationConfigProperty(propertyName = "channel", propertyValue = "SYSTEM.DEF.SVRCONN"),
@ActivationConfigProperty(propertyName = "hostName", propertyValue = "devmq1sun"),
@ActivationConfigProperty(propertyName = "queueManager", propertyValue = "DEVMQ1SUN"),
@ActivationConfigProperty(propertyName = "port", propertyValue = "1416"),
@ActivationConfigProperty(propertyName = "transportType", propertyValue = "CLIENT")
@ActivationConfigProperty(propertyName = "username", propertyValue = "foo")
@ActivationConfigProperty(propertyName = "password", propertyValue = "bar")
})
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@ResourceAdapter(value = "wmq.jmsra2.rar")
You can get rid of your desployment descriptors as the annotations take their place.(ejb-jar.xml, jboss.xml). The above example uses your resource adapter and all of your activation configuration properties. I think I got them all in there. I did notice however that you are using the "wmq.jmsra2.rar" in your ejb descriptor, but your depends in the ds.xml file is using "wmq.jmsra.rar". You may want to fix that to get the dependencies correct.
*Equivalent XML settings*
If you wanted to deploy the same thing using xml files instead of annotations, your IBM adapter will be added to your jboss.xml file
<?xml version="1.0" encoding="UTF-8"?>
<jboss
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://www.jboss.org/j2ee/schema/jboss_5_0.xsd"
version="3.0">
<enterprise-beans>
<message-driven>
<ejb-name>MyMDBName</ejb-name>
<resource-adapter-name>wmq.jmsra2.rar</resource-adapter-name>
</message-driven>
</enterprise-beans>
</jboss>
and your ejb-jar.xml file will look similar to this..
<?xml version="1.0"?>
<ejb-jar
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" version="3.0">
<enterprise-beans>
<message-driven>
<ejb-name>MyMDBName</ejb-name>
<ejb-class>test.mdb.TestMDBBean</ejb-class>
<messaging-type>javax.jms.MessageListener</messaging-type>
<transaction-type>NotSupported</transaction-type>
<activation-config>
<activation-config-property>
<activation-config-property-name>messagingType</activation-config-property-name>
<activation-config-property-value>javax.jms.MessageListener</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>destinationType</activation-config-property-name>
<activation-config-property-value>javax.jms.Queue</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>destination</activation-config-property-name>
<activation-config-property-value>queueA</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>useJNDI</activation-config-property-name>
<activation-config-property-value>true</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>channel</activation-config-property-name>
<activation-config-property-value>SYSTEM.DEF.SVRCONN</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>hostName</activation-config-property-name>
<activation-config-property-value>devmq1sun</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>queueManager</activation-config-property-name>
<activation-config-property-value>DEVMQ1SUN</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>port</activation-config-property-name>
<activation-config-property-value>1416</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>transportType</activation-config-property-name>
<activation-config-property-value>CLIENT</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>username</activation-config-property-name>
<activation-config-property-value>foo</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>password</activation-config-property-name>
<activation-config-property-value>bar</activation-config-property-value>
</activation-config-property>
</activation-config>
</message-driven>
So this is how you would deploy one mdb with the queued defined as an Admin object in your ds.xml file. The useJNDI argument makes sure that the queue will be looked up in jndi. The IBM adapter takes an Admin Object as a queue and will make the appropriate arrangements to connect to it.
The next logical question would be how do I take the Activation Configuration Properties out of the mdb and
How do I take those settings and move them out to a global place where I can define them for all MDBs?
-------------------------------------------------------------------------------------------------------
JBoss EJB3's work similar to EJB2.x, but not quite. In EJB3, the file that governs the interceptors and global settings is *NOT* the standard-jboss.xml file anymore. EJB3 now uses the deploy/ejb3-interceptors-aop.xml file. The default configuration(now it's called a domain) for all MDBs is "<domain name="Message Driven Bean">".
Defining your own domains. You can define your own domains if you wish. So if you wanted to you could copy the "Message Driven Bean" domain and rename it to something like "IBMMQ Message Driven Bean". You could add a class annotation that looks like @AspectDomain("IBMMQ Message Driven Bean")
Defining Properties in the domain. Here is the domain we were talking about.
<domain name="Message Driven Bean">
<bind pointcut="execution(public * @javax.annotation.security.RunAs->*(..))">
<interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
</bind>
<bind pointcut="execution(public * *->*(..))">
<interceptor-ref name="org.jboss.ejb3.stateless.StatelessInstanceInterceptor"/>
<interceptor-ref name="org.jboss.ejb3.tx.TxInterceptorFactory"/>
<interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
<interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
<interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/>
</bind>
<annotation expr="!class((a)org.jboss.annotation.ejb.PoolClass)">
@org.jboss.annotation.ejb.PoolClass (value=org.jboss.ejb3.StrictMaxPool.class, maxSize=30, timeout=10000)
</annotation>
</domain>
Please notice that the <annotation> tag actaully inserts a new PoolClass annotation into each MDB. This is so that you don't have to define the pool for each mdb. We are going to do the same with your other defaults. One more thing to note, the annotation expression, "<annotation expr="!class((a)org.jboss.annotation.ejb.PoolClass)">" will look to see if there is a class annotation called PoolClass. If the expression is true, then the contained PoolClass annotation is inserted. This is an important point, becuase when we put our defaults in, we can't use activationConfig, because it is already being used in the mdb. If we insert it and we already have one we will have problems. So we have to come up with another annoation to insert default activationconfig properties, called DefaultActivationSpecs. This is so that we can have some defaults along with the original activation specs that are in the mdb itself.
This would be the completed IBMMQ Message Driven Bean domain configuration.
<domain name="IBMMQ Message Driven Bean">
<bind pointcut="execution(public * @javax.annotation.security.RunAs->*(..))">
<interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
</bind>
<bind pointcut="execution(public * *->*(..))">
<interceptor-ref name="org.jboss.ejb3.stateless.StatelessInstanceInterceptor"/>
<interceptor-ref name="org.jboss.ejb3.tx.TxInterceptorFactory"/>
<interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
<interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
<interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/>
</bind>
<annotation expr="!class((a)org.jboss.annotation.ejb.PoolClass)">
@org.jboss.annotation.ejb.PoolClass (value=org.jboss.ejb3.StrictMaxPool.class, maxSize=30, timeout=10000)
</annotation>
<annotation expr="!class((a)org.jboss.annotation.ejb.DefaultActivationSpecs)">
@org.jboss.annotation.ejb.DefaultActivationSpecs ({(a)javax.ejb.ActivationConfigProperty(propertyName = "channel", propertyValue = "SYSTEM.DEF.SVRCONN"),
@javax.ejb.ActivationConfigProperty(propertyName = "hostName", propertyValue = "devmq1sun"),
@javax.ejb.ActivationConfigProperty(propertyName = "queueManager", propertyValue = "DEVMQ1SUN"),
@javax.ejb.ActivationConfigProperty(propertyName = "port", propertyValue = "1416"),
@javax.ejb.ActivationConfigProperty(propertyName = "transportType", propertyValue = "CLIENT")})
</annotation>
</domain>
+Note: All annotations must use the full class names. If you look in the EJB itself, you don't need to put the full classname because of the import. When you are injecting annotations into a class there is no import, so you must use the full classname in the ejb3-interceptors-aop.xml file.+
and your completed mdb annotations would look something like this using the new domain configuration..
@MessageDriven( name="MyMDBName",
activationConfig =
{
@ActivationConfigProperty(propertyName="messagingType",propertyValue="javax.jms.MessageListener"),
@ActivationConfigProperty(propertyName = "destinationType",propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "queueA"),
@ActivationConfigProperty(propertyName = "useJNDI", propertyValue = "true"),
})
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@ResourceAdapter(value = "wmq.jmsra2.rar")
@AspectDomain("IBMMQ Message Driven Bean")
References
[1] http://publib.boulder.ibm.com/infocenter/wmqv6/v6r0/index.jsp?topic=/com.... IBM outbound adapter properties
[2] http://www.ibm.com/developerworks/websphere/library/techarticles/0710_rit... IBM EJB 2.x instructions
--------------------------------------------------------------
Comment by going to Community
[http://community.jboss.org/docs/DOC-12944]
Create a new document in EJB3 at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=102&co...]
13 years, 9 months
[EJB3] - How to use an application client in JBoss-5
by Administrator Administrator
Administrator Administrator [http://community.jboss.org/people/admin] modified the document:
"How to use an application client in JBoss-5"
To view the document, visit: http://community.jboss.org/docs/DOC-12835
--------------------------------------------------------------
This wiki tries to explain the usage of application client container in JBoss. It consists of two parts: first an EJB is injected, the second part shows how to inject a MessageDrivenBean Queue.
h1. Injection of EJBs
In this example, we are trying to inject an EJB into an application-client and then invoke a method on that EJB in the client. +This has been tested on JBoss-5 GA. The attached example is compiled with Java5.+ So let's get started:
h6. *Step-1:Deploy th**e application*
Deploy the enterprise application which contains the EJB as well as the application-client, onto the JBoss-5 GA server. Here's what the Stateless.ear contains:
META-INF/MANIFEST.MF
StatelessEJB.jar
StatelessClient.jar
a) The StatelessEJB.jar is the jar which contains the EJB. The EJB is simple and has a couple of methods:
import javax.ejb.Stateless;
@Stateless
public class GeometricModelBean
implements GeometricModelRemote, GeometricModelLocal
{
public double computeCuboidVolume(double a, double b, double c)
{
// some code here
}
public double computeCuboidSurface(double a, double b, double c)
{
// some code here
}
}
b) The StatelessClient.jar is the application client which uses the EJB (through injection). Here's the class which has the main function:
import javax.ejb.EJB;
public class GeometricModelApplicationClient
{
*@EJB
public static GeometricModelRemote geometricModel;*
public static void main(String[] args)
{
double dblVolume;
try
{
dblVolume = geometricModel.computeCuboidVolume(10.0D, 5.0D, 7.0D);
double dblSurface = geometricModel.computeCuboidSurface(10.0D, 5.0D, 7.0D);
System.out.println("Calculated volume: " + dblVolume + ", surface: " + dblSurface);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
As you can see, the EJB is being injected in the client and later on used to invoke a method. The StatelessClient.jar should contain a application-client.xml and a jboss-client.xml (optional) to be identified as a application client. Here are the contents of these files:
+StatelessClient.jar /META-INF/application-client.xml+
<?xml version="1.0" encoding="UTF-8"?>
<application-client id="Application-client_ID" version="5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application-client_5.xsd">
<display-name>StatelessClient</display-name>
</application-client>
+StatelessClient.jar/META-INF/jboss-client.xml+:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-client PUBLIC
"-//JBoss//DTD Application Client 5.0//EN"
"http://www.jboss.org/j2ee/dtd/jboss-client_5_0.dtd">
<jboss-client>
<jndi-name>StatelessClient</jndi-name>
</jboss-client>
And then the StatelessClient.jar/META-INF/MANIFEST.MF should point to the application client class which has the main function.
+StatelessClient.jar/META-INF/MANIFEST.MF+:
Manifest-Version: 1.0
Class-Path: StatelessEJB.jar
Main-Class: de.fhw.komponentenarchitekturen.knauf.stateless.GeometricModelApplicationClient
Note that this ear does not have an application.xml. But if required, you can have one.
When this EAR is successfully deployed on the JBoss-5 GA server, you will see the following log output on the console:
13:55:57,734 INFO [JBossASKernel] Created KernelDeployment for: StatelessClient.jar
13:55:57,734 INFO [JBossASKernel] installing bean: jboss.j2ee:ear=Stateless.ear,jar=StatelessClient.jar,name=StatelessClient,service=EJB3
13:55:57,734 INFO [JBossASKernel] with dependencies:
13:55:57,734 INFO [JBossASKernel] and demands:
13:55:57,734 INFO [JBossASKernel] and supplies:
13:55:57,734 INFO [JBossASKernel] Added bean(jboss.j2ee:ear=Stateless.ear,jar=StatelessClient.jar,name=StatelessClient,service=EJB3) to KernelDeployment of: StatelessClient.jar
13:56:00,156 INFO [JBossASKernel] Created KernelDeployment for: StatelessEJB.jar
13:56:00,156 INFO [JBossASKernel] installing bean: jboss.j2ee:ear=Stateless_BrokenAppClient2.ear,jar=StatelessEJB.jar,name=GeometricModelBean,service=EJB3
13:56:00,156 INFO [JBossASKernel] with dependencies:
13:56:00,156 INFO [JBossASKernel] and demands:
13:56:00,156 INFO [JBossASKernel] jboss.ejb:service=EJBTimerService
13:56:00,156 INFO [JBossASKernel] and supplies:
13:56:00,156 INFO [JBossASKernel] jndi:Stateless/GeometricModelBean/local-de.fhw.komponentenarchitekturen.knauf.stateless.GeometricModelLocal
13:56:00,156 INFO [JBossASKernel] jndi:Stateless/GeometricModelBean/remote-de.fhw.komponentenarchitekturen.knauf.stateless.GeometricModelRemote
13:56:00,156 INFO [JBossASKernel] Class:de.fhw.komponentenarchitekturen.knauf.stateless.GeometricModelRemote
13:56:00,156 INFO [JBossASKernel] jndi:Stateless/GeometricModelBean/local
13:56:00,156 INFO [JBossASKernel] Class:de.fhw.komponentenarchitekturen.knauf.stateless.GeometricModelLocal
13:56:00,171 INFO [JBossASKernel] jndi:Stateless/GeometricModelBean/remote
13:56:00,171 INFO [JBossASKernel] Added bean(jboss.j2ee:ear=Stateless.ear,jar=StatelessEJB.jar,name=GeometricModelBean,service=EJB3) to KernelDeployment of: StatelessEJB.jar
13:56:00,437 INFO [ClientENCInjectionContainer] STARTED CLIENT ENC CONTAINER: StatelessClient
13:56:01,171 INFO [SessionSpecContainer] Starting jboss.j2ee:ear=Stateless_BrokenAppClient2.ear,jar=StatelessEJB.jar,name=GeometricModelBean,service=EJB3
13:56:01,187 INFO [EJBContainer] STARTED EJB: de.fhw.komponentenarchitekturen.knauf.stateless.GeometricModelBean ejbName: GeometricModelBean
13:56:01,203 WARN [SessionSpecContainer] Populating JBoss-specific annotation metadata manually until done by deployers: jboss.j2ee:ear=Stateless.ear,jar=StatelessEJB.jar,name=GeometricModelBean,service=EJB3
....
13:56:01,656 INFO [ServerImpl] JBoss (Microcontainer) [5.0.0.GA (build: SVNTag=JBoss_5_0_0_GA date=200809171046)] Started in 1m:8s:299ms
In your JNDIView you can now see that the application client has been bound to the JNDI:
java:comp namespace of the component jboss.j2ee:ear=Stateless.ear,jar=StatelessEJB.jar,name=GeometricModelBean,service=EJB3 :
+- EJBContext (class: javax.ejb.EJBContext)
+- TransactionSynchronizationRegistry[link -> java:TransactionSynchronizationRegistry] (class: javax.naming.LinkRef)
+- UserTransaction (class: org.jboss.ejb3.tx.UserTransactionImpl)
+- env (class: org.jnp.interfaces.NamingContext)
+- ORB[link -> java:/JBossCorbaORB] (class: javax.naming.LinkRef)
Global JNDI Namespace
+- StatelessClient (class: org.jnp.interfaces.NamingContext)
| +- UserTransaction[link -> UserTransaction] (class: javax.naming.LinkRef)
| +- metaData (class: org.jboss.metadata.client.jboss.JBossClientMetaData)
| +- env (class: org.jnp.interfaces.NamingContext)
| | +- geometricModel[link -> Stateless/GeometricModelBean/remote-de.fhw.komponentenarchitekturen.knauf.stateless.GeometricModelRemote] (class: javax.naming.LinkRef)
| +- classPathEntries (class: java.util.ArrayList)
h6. *Step-2: Use the* *appclient-launcher to launch the application client container.*
Now that the EAR containing the bean and the application client has been deployed, the next step is to launch the application client container. Note: Just running the application client class through a java command will not get the injection working. You need the launcher to provide the application server functionalities.
>From the command prompt, 'cd' to %JBOSS_HOME%\client folder. I have JBoss installed in D:\jboss-5.0.0.GA so from my command prompt, i will cd to D:\jboss-5.0.0.GA\client folder:
D:\jboss-5.0.0.GA\client>set JBOSS_HOME=d:\jboss-5.0.0.GA
D:\jboss-5.0.0.GA\client>set JAVA_HOME=c:\jdk1.6.0_10
D:\jboss-5.0.0.GA\client>set PATH=%JAVA_HOME%\bin;%PATH%
Now use the following command to launch the application client container:
D:\jboss-5.0.0.GA\client>%JAVA_HOME%\bin\java -Djava.naming.factory.initial=org.jnp.interfaces.NamingContextFactory -Djava.naming.provider.url=jnp://localhost:1099 -classpath "%JBOSS_HOME%\client\jbossall-client.jar;%JBOSS_HOME%\client\jboss-metadata.jar;%JBOSS_HOME%\lib\jboss-classloader.jar;%JBOSS_HOME%\lib\jboss-classloading-spi.jar;%JBOSS_HOME%\lib\jboss-classloading-vfs.jar;%JBOSS_HOME%\lib\jboss-classloading.jar;%JBOSS_HOME%\lib\jboss-dependency.jar;%JBOSS_HOME%\lib\jboss-reflect.jar;%JBOSS_HOME%\lib\jboss-kernel.jar;%JBOSS_HOME%\lib\jboss-xml-binding.jar;%JBOSS_HOME%\lib\jboss-xml-binding.jar;%JBOSS_HOME%\lib\jboss-vfs.jar;%JBOSS_HOME%\lib\jboss-reflect.jar;%JBOSS_HOME%\common\lib\jboss-ejb3-core.jar" org.jboss.client.AppClientMain -jbossclient de.fhw.komponentenarchitekturen.knauf.stateless.GeometricModelApplicationClient -launchers org.jboss.ejb3.client.ClientLauncher -j2ee.clientName StatelessClient
The entire command should be in one single line. The important things to note in this command (other than the classpath stuff) is that:
a) We are passing the JNDI related properties:
-Djava.naming.factory.initial=org.jnp.interfaces.NamingContextFactory -Djava.naming.provider.url=jnp://localhost:1099
The -Djava.naming.provider.url should point to the server's Naming port.
*+Where is the "-Djava.naming.factory.url.pkgs" argument?+*
This argument is required, if the client app performs a JNDI lookup itself, and it's value has to be "org.jboss.naming.client".
But this one is not used by the Injection framework. jaikirans investigations found that the environment property Context.URL_PKG_PREFIXES does not come into picture when using injection because of the way org.jboss.ejb3.client.JNDIDependencyItem is working. It does not look into the java:comp/env namespace but just looks up and adds a dependency on StatelessClient/metaData jndiname. Later on when the actual lookup for java:comp/env namespace is done on the jndi *server*, the properties that are on the server are used.
b) We are calling the org.jboss.client.AppClientMain which is the application client container's entry point
c) We are passing -jbossclient parameter and its corresponding value de.fhw.komponentenarchitekturen.knauf.stateless.GeometricModelApplicationClient to org.jboss.client.AppClientMain. This is your application client main class which uses the EJB
d) We are also passing the -j2ee.clientName which is the name of your application client to org.jboss.client.AppClientMain. In this case, its StatelessClient.
e) We are passing the -launchers org.jboss.ejb3.client.ClientLauncher to org.jboss.client.AppClientMain. This one is important. The -launchers accepts a comma separate list of fully qualified implementations of org.jboss.client.AppClientLauncher interface. The org.jboss.ejb3.client.ClientLauncher is one such implementation (provided by JBoss) which is responsible for injecting EJB (and some other things) in the application client.
h6. *Step-3: See th**e output.*
When you run the command mentioned in Step-2, the application client container will invoke the main method of your application client. In our example, the main method uses the injected EJB and invokes a method on the EJB and finally prints the following output on the client side:
Calculated volume: 350.0, surface: 310.0
Note, on the server side you might see the EJB related logs (if you have any logging messages).
That's it!
*P.S: The application attached here is provided by Wolfgang Knauf* http://www.jboss.com/index.html?module=bb&op=viewtopic&t=143595 http://www.jboss.com/index.html?module=bb&op=viewtopic&t=143595
h5. Why don't i see logs on the application client side?
By default, with the command used in Step-2, you will not see the log message. The log messages are really useful when debugging any issue. You have to do 2 things to see logs on the client side:
1) Add log4j.jar to the client classpath
2) Add a log4j properties or xml file to the classpath or pass -Dlog4j.configuration=[path to log4j config file] JVM option.
On my setup, i created a log4j.properties file with the following settings:
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%t][%c] - <%m>%n
And then placed this file under %JBOSS_HOME%\client folder. Finally i changed the java command (in Step-2) to include the log4j.jar and also pass this log4j configuration file path as a JVM option. Here's the updated command:
D:\jboss-5.0.0.GA\client>%JAVA_HOME%\bin\java -Djava.naming.factory.initial=org.jnp.interfaces.NamingContextFactory -Djava.naming.provider.url=jnp://localhost:1099 -Dlog4j.configuration=%JBOSS_HOME%\client\log4j.properties -classpath "%JBOSS_HOME%\client\jbossall-client.jar;%JBOSS_HOME%\client\jboss-metadata.jar;%JBOSS_HOME%\client\log4j.jar;%JBOSS_HOME%\lib\jboss-classloader.jar;%JBOSS_HOME%\lib\jboss-classloading-spi.jar;%JBOSS_HOME%\lib\jboss-classloading-vfs.jar;%JBOSS_HOME%\lib\jboss-classloading.jar;%JBOSS_HOME%\lib\jboss-dependency.jar;%JBOSS_HOME%\lib\jboss-reflect.jar;%JBOSS_HOME%\lib\jboss-kernel.jar;%JBOSS_HOME%\lib\jboss-xml-binding.jar;%JBOSS_HOME%\lib\jboss-vfs.jar;%JBOSS_HOME%\lib\jboss-reflect.jar;%JBOSS_HOME%\common\lib\jboss-ejb3-core.jar" org.jboss.client.AppClientMain -jbossclient de.fhw.komponentenarchitekturen.knauf.stateless.GeometricModelApplicationClient -launchers org.jboss.ejb3.client.ClientLauncher -j2ee.clientName StatelessClient
If Log4j does not show the expected results, add "-Dlog4j.debug=true" to the startup parameters, which will print Log4j debugging output and hopefully point you to the reason why e.g. the config file could not be found.
h5.
h1. Injection of a Queue
(credits for this chapter go to jaikiran, I (Wolfgang) just documented his findings here, see http://www.jboss.org/index.html?module=bb&op=viewtopic&t=149330 http://www.jboss.org/index.html?module=bb&op=viewtopic&t=149330 ).
Assume a client that wants to send data to a queue (e.g. a Message Driven Bean).
You need a javax.jms.QueueConnectionFactory and a javax.jms.Queue, which will be injected by the container. As they are injected, they must be static variables in the class containing the "main" method (annotations will be added later):
private static QueueConnectionFactory queueConnectionFactory;
private static Queue queue;
This is the code to send the message (one more "Hello World" sample ;-) ):
QueueConnection queueConnection = queueConnectionFactory.createQueueConnection();
QueueSession queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueSender queueSender = queueSession.createSender(queue);
//Send a text message:
TextMessage textMessage = queueSession.createTextMessage();
textMessage.setText("Hello World");
queueSender.send(textMessage);
There are two possibilities to inject the Queue and QueueConnectionFactory.
We assume that our Queue (which points to a MDB) is bound to the global JNDI name "queue/MessageBeanQueue". The QueueConnectionFactory is provided by JBoss (you can find it in the JMXConsole as ObjectName "jboss.messaging.connectionfactory").
h5. 1) From global JNDI
This one is easy: the "mappedName" attribute of the @Resource annotation points to the global JNDI names:
@Resource(mappedName="ConnectionFactory")
private static QueueConnectionFactory queueConnectionFactory;
@Resource(mappedName="queue/MessageBeanQueue")
private static Queue queue;
h5. 2) From Environment Naming Context (ENC)
The "name" attribute of the @Resource annotation points to ENC names:
@Resource(name="jms/MBConnectionFactory")
private static QueueConnectionFactory queueConnectionFactory;
@Resource(name="jms/MBQueueRef")
private static Queue queue;
Here you need two config files:
*application-client.xml* looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<application-client id="Application-client_ID" version="5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application-client_5.xsd">
...
<resource-ref>
<res-ref-name>jms/MBConnectionFactory</res-ref-name>
<res-type>javax.jms.QueueConnectionFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<message-destination-ref>
<message-destination-ref-name>jms/MBQueueRef</message-destination-ref-name>
<message-destination-type>javax.jms.Queue</message-destination-type>
</message-destination-ref>
</application-client>
The QueueConnectionFactory as declared as a resource-ref, while the Queue is declared as a message-destination-ref !
*jboss-client.xml* handles the binding of the ENC entries to JBoss JNDI names:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-client PUBLIC
"-//JBoss//DTD Application Client 5.0//EN"
"http://www.jboss.org/j2ee/dtd/jboss-client_5_0.dtd">
<jboss-client>
<jndi-name>...</jndi-name>
<resource-ref>
<res-ref-name>jms/MBConnectionFactory</res-ref-name>
<jndi-name>ConnectionFactory</jndi-name>
</resource-ref>
<message-destination-ref>
<message-destination-ref-name>jms/MBQueueRef</message-destination-ref-name>
<jndi-name>queue/MessageBeanQueue</jndi-name>
</message-destination-ref>
</jboss-client>
Same as in application-client.xml: The Queue must be declared as a message-destination-ref
A full sample can be found here: http://www.informatik.fh-wiesbaden.de/~knauf/KomponentenArchitekturen2008... http://www.informatik.fh-wiesbaden.de/~knauf/KomponentenArchitekturen2008... (compiled with Java 1.6, will not run with 1.5)
It contains an EJB module with a MDB, and an application client module (simple swing client with a JTextField whose content is sent to the server). The queue is declared in the module with a -service.xml file in the EJB module. Simply deploy it to the server. To run the client: extract "MessageClient.jar" from the EAR to some other directory, and start the client using the ClientLauncher (see step 2 above).
The code is commented in German, but hopefully you will understand it anyway ;-)
--------------------------------------------------------------
Comment by going to Community
[http://community.jboss.org/docs/DOC-12835]
Create a new document in EJB3 at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=102&co...]
13 years, 9 months
[EJB3] - How do the timeouts work with EJB3 Stateful Beans
by Administrator Administrator
Administrator Administrator [http://community.jboss.org/people/admin] modified the document:
"How do the timeouts work with EJB3 Stateful Beans"
To view the document, visit: http://community.jboss.org/docs/DOC-9628
--------------------------------------------------------------
h2. EJB3 Timeouts with Stateful Session Beans
h3. When using stateful session beans, you can control the timeouts for.
1. How long the bean(with the state) remains in memory. State can be passivated to disk(or cache) to free up memory for other beans or processes.
2. How long the bean remains active before it is completely removed. This controls the life span of the SFSB.
h3. There are two timeouts that control this:
1. idleTimeoutSeconds - the number of seconds that a SFSB remains active but unused until the state is passivated.
2. removalTimeoutSeconds - this represents the end of the beans life, the bean and state are deleted when this timeout is hit but the bean was unused. 0 represents infinity. When removalTimeoutSeconds <= idleTimeoutSecond, then the bean is not passivated, it is just straightforwardly removed.
h3. You can change this in two places.
h4. 1. You can change the timeouts per bean by defining a class annotation.
For a clustered configuration specify a simple CacheConfig with your specific timeouts. Remember that 0 is infinite.
*If you are NOT in a clustered app server..*
@CacheConfig (maxSize=100000, idleTimeoutSeconds=300, removalTimeoutSeconds=0)
*If you are IN a clustered app server..*
@CacheConfig (name="jboss.cache:service=EJB3SFSBClusteredCache", maxSize=100000, idleTimeoutSeconds=300, removalTimeoutSeconds=0)
h4. 2. You can change these globally if you go to the deploy/ejb3-interceptors-aop.xml file.
You will see the following defined for clustered and non clustered SFSBs. Just edit the file and replace the timouts that you would like. Make sure that you change the correct one if you are clustered or non-clustered. You may want to change both for constancy.
<annotation expr="!class((a)org.jboss.annotation.ejb.cache.simple.CacheConfig) AND !class((a)org.jboss.annotation.ejb.Clustered)">
@org.jboss.annotation.ejb.cache.simple.CacheConfig (maxSize=100000, idleTimeoutSeconds=300, removalTimeoutSeconds=0)
</annotation>
<!-- Clustered cache configuration -->
<annotation expr="!class((a)org.jboss.annotation.ejb.cache.Cache) AND class((a)org.jboss.annotation.ejb.Clustered)">
@org.jboss.annotation.ejb.cache.Cache (org.jboss.ejb3.cache.tree.StatefulTreeCache.class)
</annotation>
<annotation expr="!class((a)org.jboss.annotation.ejb.cache.tree.CacheConfig) AND class((a)org.jboss.annotation.ejb.Clustered)">
@org.jboss.annotation.ejb.cache.tree.CacheConfig (name="jboss.cache:service=EJB3SFSBClusteredCache", maxSize=100000, idleTimeoutSeconds=300, removalTimeoutSeconds=0)
</annotation>
*Warning:*Be careful what you set the removalTimeoutSeconds to. If you are in the middle of a session and bean is not touched, it's possible that you could end up in a condition where you are depending on the state, you haven't touched it in the given timeout and the state is suddenly gone. You will get the following errror...
javax.ejb.EJBNoSuchObjectException: Could not find Stateful bean: 41z4l26-wb41k6-ev4j007b-1-ev4jirql-bw
ref:
(1.) timout setting for seam. JbossTimeoutSettingForSeam
--------------------------------------------------------------
Comment by going to Community
[http://community.jboss.org/docs/DOC-9628]
Create a new document in EJB3 at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=102&co...]
13 years, 9 months
[EJB3] - Accessing_EJB3s_over_SSL
by Administrator Administrator
Administrator Administrator [http://community.jboss.org/people/admin] modified the document:
"Accessing_EJB3s_over_SSL"
To view the document, visit: http://community.jboss.org/docs/DOC-9050
--------------------------------------------------------------
h2. EJB3 over SSL
This tutorial shows you how to invoke remote EJBs over an SSL connection.
Setting up SSL for use in EJB3 involves creating a keystore and making sure the correct transport
is available in the EJB3 configuration. After which you only have to use the RemoteBinding annotation
with a clientBindUrl to make sure the bean is called through SSL.
This tutorial assumes you've setup JBoss 4.x with EJB3 support. Make sure the enviroment variable
JBOSS_HOME refers to the installation directory.
h3. Creating a keystore
For SSL to work we need to create a public/private key pair, which will be stored in a keystore. Generate this using the genkey command that comes with the JDK.
$ cd $JBOSS_HOME/server/default/conf/
$ keytool -genkey -alias ejb3-ssl -keypass opensource -keystore localhost.keystore
Enter keystore password: opensource
What is your first and last name?
[Unknown]:
What is the name of your organizational unit?
[Unknown]:
What is the name of your organization?
[Unknown]:
What is the name of your City or Locality?
[Unknown]:
What is the name of your State or Province?
[Unknown]:
What is the two-letter country code for this unit?
[Unknown]:
Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
[no]: yes
Since we have not signed our certificate through any certification authoritiy, we also need to create a truststore for the client, explicitly saying that we trust the certificate we just created. The first step is to export the certificate using the JDK keytool:
$ keytool -export -alias ejb3-ssl -file mycert.cer -keystore localhost.keystore
Enter keystore password: opensource
Certificate stored in file <mycert.cer>
Then we need to create the truststore if it does not exist and import the certificate into the trueststore:
$ keytool -import -alias ejb3-ssl -file mycert.cer -keystore localhost.truststore
Enter keystore password: opensource
Owner: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
Issuer: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
Serial number: 43bff927
Valid from: Sat Jan 07 18:23:51 CET 2006 until: Fri Apr 07 19:23:51 CEST 2006
Certificate fingerprints:
MD5: CF:DC:71:A8:F4:EA:8F:5A:E9:94:E3:E6:5B:A9:C8:F3
SHA1: 0E:AD:F3:D6:41:5E:F6:84:9A:D1:54:3D:DE:A9:B2:01:28:F6:7C:26
Trust this certificate? [no]: yes
Certificate was added to keystore
h3. Setting up the transport
To setup the transport open $JBOSS_HOME/server/default/deploy/ejb3.deployer/META-INF/jboss-service.xml in your
favorite text editor. Add the following mbean to it:
<mbean code="org.jboss.remoting.transport.Connector"
name="jboss.remoting:type=Connector,transport=socket3843,handler=ejb3">
<depends>jboss.aop:service=AspectDeployer</depends>
<attribute name="InvokerLocator">sslsocket://0.0.0.0:3843</attribute>
<attribute name="Configuration">
<handlers>
<handler subsystem="AOP">org.jboss.aspects.remoting.AOPRemotingInvocationHandler</handler>
</handlers>
</attribute>
</mbean>
h3. Starting JBoss
We need to tell JBoss Remoting where to find the keystore to be used for SSl and its password. This is done using
the javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword=opensource system properties when starting JBoss, as
the following example shows:
$ cd $JBOSS_HOME/bin
$ ./run.sh -Djavax.net.ssl.keyStore=../server/default/conf/localhost.keystore -Djavax.net.ssl.keyStorePassword=opensource
h3. Creating your beans
Create your EJBs as usual and add the following annotation to bind it to the SSL invoker.
import org.jboss.annotation.ejb.RemoteBinding;
@RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843")
For the purpose this tutorial an example bean is provided (see src/org/jboss/tutorial/ssl/bean/CalculatorBean.java).
To compile and deploy the example simple execute ant ejbjar.
h3. Running your client
While making sure all the correct libraries are on the classpath we can run the provided client.
$ java -Djavax.net.ssl.trustStore=$JBOSS_HOME/server/default/conf/localhost.truststore -Djavax.net.ssl.trustStorePassword=opensource org.jboss.tutorial.ssl.client.Client
Or better yet, just run ant run.
--------------------------------------------------------------
Comment by going to Community
[http://community.jboss.org/docs/DOC-9050]
Create a new document in EJB3 at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=102&co...]
13 years, 9 months
[EJB3] - EJB3 relationships
by Administrator Administrator
Administrator Administrator [http://community.jboss.org/people/admin] modified the document:
"EJB3 relationships"
To view the document, visit: http://community.jboss.org/docs/DOC-13222
--------------------------------------------------------------
This page gives some HowTos about handling EJB3 relationships, and it points to some common problems and error messages.
It is written by a JBoss user, not a guru ;-).
For questions and comments mail me at: wolfgang DOT knauf AT gmx DOT de
h1. Declaration of relationships
h2. Datatype
It sounds easy to use lists (implementations of java.util.List) for the "to many" part of the relationship. This is normally no problem, but in combination with FetchType.EAGER it might result in deployment errors (see below).
Those problems do not occur, if a java.util.Set is used. In most use cases, this is the better approach, because in a "to many" relation, there will be probably no duplicates. Only if duplicates are allowed, a java.util.List should be used.
h2. "mappedBy"
To create a bidirectional relationship, you have to connect the two sides with a "mappedBy" attribute on one of the two sides of the relation. The "mappedBy" specifies the property name of the other side. The property without "mappedBy" is the *defining side* of the relation.
Example:
@Entity()
public class ParentBean implements Serializable
{
private Set<ChildBean> listChilds = new HashSet<ChildBean>();
@OneToMany(*mappedBy="parent"*)
public Set<ChildBean> getChilds()
{
return this.listChilds;
}
}
@Entity()
public class ChildBean implements Serializable
{
@ManyToOne ()
public ParentBean get*Parent*()
{
return this.parent;
}
}
If you want to specify e.g. a @JoinTable, you must do this on the defining side of the relation. On the "mappedBy" side, this annotation will have no effect (not even an error message).
h2. FetchType
There are two fetch types available:
* FetchType.EAGER: the relationship fields should be fetched immediately when loading the parent field.
* FetchType.LAZY: the relationship fields should be fetched when necessary (e.g. when they are accessed).
Both sides have drawbacks, so there is no easy decision for either of them.
*FetchType.EAGER:*
* Benefit: easier to code, because the field is always populated by the server.
* Drawback: performance: if the parent relationship is loaded, all its relationship fields are populated, too.
* Drawback: If an entity has more than one relationship field, this exception may occur on publish:
javax.persistence.PersistenceException: [PersistenceUnit: ...] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:677)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:132)
at org.jboss.jpa.deployment.PersistenceUnitDeployment.start(PersistenceUnitDeployment.java:311)
...
Caused by: *org.hibernate.HibernateException: cannot simultaneously fetch multiple bags*
at org.hibernate.loader.BasicLoader.postInstantiate(BasicLoader.java:89)
at org.hibernate.loader.entity.EntityLoader.(EntityLoader.java:98)
...
For an explanation and workarounds see here: http://jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetc... http://jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetc....
In short: try to use LAZY where possible, or replace java.util.List collections by java.util.Set.
*FetchType.LAZY:*
* Benefit: performance: on loading the entity, only the data of the entity itself is fetched. No relationship fields are populated.
* Drawback: the relationship fields can only be lazily loaded when the entity bean is under entity manager control ("attached"). As soon as it becomes "detached", accessing an unloaded relationship field will result in this exception:org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: my.package.ParentBean.childs, no session or session was closed
org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
...
The workaround for this is to force loading of the relationship fields while it is still attached. This must happen in the session bean where it is loaded. So, if you have a method "findById" in your session bean, add the bold line: public ParentBean findById (Integer int_ParentId)
{
ParentBean parentBean = this.entityManager.find(ParentBean.class, int_ParentId);
*if (parentBean != null)
{
parentBean.getChilds().size();
}*
return parentBean;
}
I included a NULL check, because "find" returns NULL if the ID is invalid. Important: a call to parentBean.getChilds() does not fetch the childs. You have to access the content of the collection to fetch them. I did this by calling "size()".
This prefetching has to be handled with care: check your use cases and verify that preloading makes sense. Otherwise, you might load unnecessary data, and this slows your app down.
*Default Values:*
The defaults for the "fetch" attribute differ beetween the different relationship types.
* @OneToMany: LAZY
* @ManyToOne: EAGER
* @OneToOne: EAGER
* @ManyToMany: LAZY
*EntityManager.find versus getReference*
"find" returns NULL if the entity is not found. "getReference" throws a javax.persistence.EntityNotFoundException, if nothing is found.
There is another major difference beetween the two: "getReference" does *not* load relationship fields, even if they are set to "EAGER". This results in the org.hibernate.LazyInitializationException if the entity gets detached and the relationship is accessed. On the other hand, it might improve performance if you have a bit of session bean code, where you don't need the relationship fields.
h2. CascadeType
*CascadeType.REMOVE*
This is the one which requires most thinking about. It depends on your use case, whether it makes sense to delete the childs, when the parent is deleted. For @ManyToMany-Relationships, a CascadeType.REMOVE is always wrong.
A CascadeType.REMOVE does *not* mean "remove connection beetween child and parent, if parent is deleted", it means "delete child".
Assume you have a one-to-many relation beetween parent and child without CascadeType.REMOVE, and you want to delete a parent with childs, you will see this (quite meaningless) exception in the server console:
13:50:10,687 WARN [JDBCExceptionReporter] SQL Error: 0, SQLState: null
13:50:10,687 ERROR [JDBCExceptionReporter] failed batch
13:50:10,687 ERROR [AbstractFlushingEventListener] Could not synchronize database state with session
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:126)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:114)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
...
Caused by: java.sql.BatchUpdateException: failed batch
at org.hsqldb.jdbc.jdbcStatement.executeBatch(Unknown Source)
at org.hsqldb.jdbc.jdbcPreparedStatement.executeBatch(Unknown Source)
at org.jboss.resource.adapter.jdbc.CachedPreparedStatement.executeBatch(CachedPreparedStatement.java:474)
...
13:50:10,703 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_2] TwoPhaseCoordinator.beforeCompletion - failed for com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple@1fb6021
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:614)
at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:513)
at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:101)
at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:263)
at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:86)
at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:177)
...
"server.log" gave me a bit more of information:
2008-12-28 13:50:10,687 DEBUG [org.hibernate.util.JDBCExceptionReporter] (http-127.0.0.1-8080-1) Could not execute JDBC batch update [delete from ParentBean where id=?]
...(same stacktrace as above)
If it is intended to keep the child (no cascading of the deletion), then you first have to remove the child from the relationship (see chapter "Managing the (bidirectional) relationship - Deleting an item" below).
*CascadeType.PERSIST and CascadeType.MERGE*
There is not much to say about them. I think you can set those flags whereever you want without drawbacks.
Leaving those flags might be a problem, if your use cases allows modification of parent and childs in one step (so that saving the parent should also save the childs). If you dont' activate this flag, then only the parent is saved, but not the childs.
*CascadeType.REFRESH*
Same as above: I think you can set those flags whereever you want without drawbacks.
*CascadeType.ALL*
Combination of all the above, so set it only, if you are sure about CascadeType.REMOVE.
h1. Managing the (bidirectional) relationship
This chapters describes how to handle bidirectional relationships in code.
The major clue is: always perform actions on both sides of a relation!
My general advice is to place manipulation of relationships in the session bean layer. If you build methods like "addChildToParent(ParentBean parent, ChildBean child)" or "removeChildToParentMapping (ParentBean parent, ChildBean child)", then you have encapsulated the relationship handling in one place. And more important: if you load the entitities from database in the beginning of this method, you will not have problems with detached entitities.
*Adding an item*
Here is a sample for a @OneToMany relationship (a parent has many childs): Two childs shall be added to the parent.
ParentBean parent = ...;
ChildBean child1 = ...;
parent.getChilds().add(child1);
child1.setParent(parent);
ChildBean child2 = ...;
parent.getChilds().add(child2);
child2.setParent(parent);
this.entityManager.merge(parent);
Important: add the new child to the child list of the parent, *and* set the parent in the child.
If the line child1.setParent(parent); was left, the childs database column "parentid" would be NULL, thus the child would not be connected to the parent.
The same approach is used for @ManyToMany relationships:
LeftBean left = ...;
RightBean right = ...;
left.getRights().add(right);
right.getLefts().add(left);
this.entityManager.merge(left);
*Removing an item*
If you want to remove an item from a relationship (without deleting either entity bean), you have to perform this code:
ParentBean parent = ...;
ChildBean child = ...;
parent.getChilds().remove(child);
child.setParent(null);
this.entityManager.merge(parent);
This leaves the child in database with the "ParentID" column being NULL.
If you leave the line child.setParent(null);, you will be surprised to find out the child and parent are still connected.
For a @ManyToMany relationship, it might look like this:
LeftBean leftBean = this.entityManager.find(LeftBean.class, int_LeftId);
RightBean rightBean = this.entityManager.find(RightBean.class, int_RightId);
leftBean.getRights().remove(rightBean);
rightBean.getLefts().remove(leftBean);
this.entityManager.persist(leftBean);
*Deleting an item*
If you actually want to delete an item, and you don't cascade removal, you may see two kinds of exceptions, depending on the kind of relationship you use.
*1) Deleting the parent side*
If you delete a parent with childs, you will see the exceptions shown in the above chapter "Declaration of relationships - CascadeType - CascadeType.REMOVE".
The solution is to first remove the relationship before deleting the object. Here is a sample for a @ManyToMany relationship:
public void deleteLeft(Integer int_LeftId)
{
LeftBean leftBean = this.entityManager.find(LeftBean.class, int_LeftId);
for (RightBean rightBean : leftBean.getRights())
{
rightBean.getLefts().remove(leftBean);
}
this.entityManager.remove(leftBean);
}
After fetching the LeftBean, I loop over the relation to the RightBean. For each relationship element RightBean, I remove the LeftBean from the collection. Afterwards, I can persist it.
*2) Deleting the child side*
This exception seems to happen only on the "ToOne" side of a "@ManyToOne" relationship.
javax.ejb.EJBTransactionRolledbackException: Transaction rolled back
org.jboss.ejb3.tx.Ejb3TxPolicy.handleEndTransactionException(Ejb3TxPolicy.java:54)
org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:175)
org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:87)
org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:190)
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
...
code to your session bean
...
Caused by: javax.transaction.RollbackException: [com.arjuna.ats.internal.jta.transaction.arjunacore.commitwhenaborted] [com.arjuna.ats.internal.jta.transaction.arjunacore.commitwhenaborted] Could not commit transaction.
com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1426)
com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:135)
com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:75)
org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:170)
org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:87)
org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:190)
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
...
Caused by: javax.persistence.EntityNotFoundException: deleted entity passed to persist: [org.jboss.wiki.relationships.eager.ChildEagerBean#]
org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:598)
org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:513)
com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:101)
com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:263)
com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:86)
com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:177)
com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1414)
com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:135)
com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:75)
org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:170)
The solution is the same as above: remove the child from the parents collection first:
public void deleteChild (Integer int_ChildId)
{
ChildBean child = this.entityManager.getReference(ChildBean.class, int_ChildId);
child.getParent().getChilds().remove(child);
this.entityManager.remove(child);
}
h1. Entity Bean as JoinTable
This chapter describes how to create a Entity Bean "ParentToChildBean" for a ManyToMany-mapping beetween two other entities named "ParentBean" and "ChildBean" (so that both of those just form an OneToMany to the mapping entity. If the JPA specification allowed us to declare IDs on relation fields, this would be easy, but unfortunately something like this declaration in "ParentToChildBean" is illegal:
@ManyToOne
@Id
public ChildBean getChild()
{
..
}
*The fields of the Entity:*
So, we have to do use a trick: we declare the relation, and we duplicate the primary key fields of the "ParentBean" and "ChildBean" entities. This sample assumes that both have an Integer Id.
private Integer iParentId;
private Integer iChildId;
private Parent parent;
private Child child;
@Id
public Integer getParentId()
{
...
}
@Id
public Integer getChildId()
{
...
}
@ManyToOne
public ParentBean getParent()
{
...
}
@ManyToOne
public ChildBean getChild()
{
...
}
//TODO: setters
*Cleaning up the database structure:*
This results in one problem: the Id fields result in database columns, and the relationship fields create foreign key columns, too. So, we have to tell the server
1) to use the same column names for Id fields and relationships and
2) not to add the relationship fields to insert/update statements.
This is a sample for the "parentId", same applies to the "childId".
@Id
@Column(name="PARENTID")
public Integer getParentId()
{
}
@ManyToOne
@JoinColumn(name="PARENTID", insertable=false, updatable=false)
public ParentBean getParent()
{
...
}
The annotation "@JoinColumn" declares that the relationship columns should map to a column named "PARENTID", which is also the name of the "parentId" field. The attributes "insertable" and "updateable" must be set to "false" so that JBoss does not add them twice to insert/updates. If they were not set, this would result in this error:
java.sql.SQLException: Column count does not match in statement [insert into ParentToChildBean (PARENTID, CHILDID, ..., other fields, ..., PARENTID, CHILDID) values (?, ?, ..., ?, ?)]
at org.hsqldb.jdbc.Util.throwError(Unknown Source)
at org.hsqldb.jdbc.jdbcPreparedStatement.(Unknown Source)
at org.hsqldb.jdbc.jdbcConnection.prepareStatement(Unknown Source)
...
*Cleaning up code:*
There is one more thing to handle: the id fields may not differ from the relationship field values. So, I advice to
1) declare getters and setters of the id fields as "private". The relationship shall only be accessed through the one-to-many properties. The private setters are required anyway, because JBoss uses them to set the values on loading the entity. We might have used field based property access to avoid them, but I prefer the property based field access.
2) the setters of the one-to-many properties must update the id fields!
Here is the full code:
@Entity
@IdClass(value=ParentToChildPK.class)
public class ParentToChildEntity implements Serializable
{
private Integer iParentId;
private Integer iChildId;
private Parent parent;
private Child child;
@Id
@Column(name="PARENTID")
*@SuppressWarnings("unused")
private* Integer getParentId()
{
return this.iParentId;
}
*@SuppressWarnings("unused")
private* void setParentId(Integer iParentIdNew)
{
this.iParentId = iParentIdNew;
}
@Id
@Column(name="CHILDID")
*@SuppressWarnings("unused")
private* Integer getChildId()
{
return this.iChildId;
}
*@SuppressWarnings("unused")
** private* void setChildId(Integer iChildIdNew)
{
this.iChildId = iChildIdNew;
}
@ManyToOne
@JoinColumn(name="PARENTID", insertable=false, updatable=false)
public ParentBean getParent()
{
return this.parent;
}
public void setParent(ParentBean parentNew)
{
this.parent = parentNew;
*if (parentNew != null)
this.iParentId = parentNew.getId();
else
this.iParentId = null;*
}
@ManyToOne
@JoinColumn(name="CHILDID", insertable=false, updatable=false)
public ChildBean getChild()
{
return this.child;
}
public void setChild(ChildBean childNew)
{
this.child = childNew;
*if (childNew != null)
this.iChildId = childNew.getId();
else
this.iChildId = null;*
}
}
*ID Class:*
Now we are nearly done. The only thing left is an id class. This one contains an exact copy of the id fields! The names *must* not differ!
public class ParentToChildPK implements Serializable
{
private Integer iParentId;
private Integer iChildId;
public Integer getParentId()
{
return this.iParentId;
}
public void setParentId(Integer iParentIdNew)
{
this.iParentId = iParentIdNew;
}
public Integer getChildId()
{
return this.iChildId;
}
public void setChildId(Integer iChildIdNew)
{
this.iChildId = iChildIdNew;
}
}
The Id class has to be declared on the entity:
@Entity()
*(a)IdClass(**ParentToChildPK.class)*
public class ParentToChildBean implements Serializable
{
...
We need the Id class because if it was missing,...
* ...saving a ParentToChildBean would result in this error:
14:32:44,281 WARN [JDBCExceptionReporter] SQL Error: 0, SQLState: null
14:32:44,281 ERROR [JDBCExceptionReporter] failed batch
14:32:44,281 ERROR [AbstractFlushingEventListener] Could not synchronize database state with session
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:126)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:114)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
...
Caused by: java.sql.BatchUpdateException: failed batch
at org.hsqldb.jdbc.jdbcStatement.executeBatch(Unknown Source)
at org.hsqldb.jdbc.jdbcPreparedStatement.executeBatch(Unknown Source)
at org.jboss.resource.adapter.jdbc.CachedPreparedStatement.executeBatch(CachedPreparedStatement.java:476)
at org.jboss.resource.adapter.jdbc.WrappedStatement.executeBatch(WrappedStatement.java:774)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 65 more
If sql logging is activated, the real reason is clear:
insert into ParentToChildBean (PARENTID, other fields) values (?, ...)
The field "CHILDID" is missing.
* Loading of a "ParentToChildBean" would not be possible, because "EntityManager.getReference" needs a primary key class for concatenated primary keys.
h2. Alternate way: EmbeddedId
The previous sample had one drawback: the id fields had to be duplicated to entity and primary key class.
*Embedded ID class:*
To avoid this, we create an EmbeddedId class. This one is nearly the same as the primary key class:
import javax.persistence.Embeddable;
*@Embeddable*
public class ParentToChildPK implements Serializable
{
private Integer iParentId;
private Integer iChildId;
***@Column(name="PARENTID")*
public Integer getParentId()
{
return this.iParentId;
}
public void setParentId(Integer iParentIdNew)
{
this.iParentId = iParentIdNew;
}
*@Column(name="CHILDID")*
public Integer getChildId()
{
return this.iChildId;
}
public void setChildId(Integer iChildIdNew)
{
this.iChildId = iChildIdNew;
}
}
There are two differences to the primary key class:
* It has the annotation "javax.persistence.Embeddable"
* The column names are defined on this class (but could be overridden if the embedded id was used for different entities)
*Entity "ParentToChildBean":*
The entity code is a bit simpler now:
import javax.persistence.EmbeddedId;
...
@Entity
public class ParentToChildBean implements Serializable
{
*private* *ParentToChildPK pk;*
private Parent parent;
private Child child;
*@EmbeddedId*
@SuppressWarnings("unused")
private ParentToChildPK getPk()
{
return this.pk;
}
@SuppressWarnings("unused")
private void setPk(ParentToChildPK pk)
{
this.pk = pk;
}
@ManyToOne
@JoinColumn(name="PARENTID", insertable=false, updatable=false)
public ParentBean getParent()
{
return this.parent;
}
public void setParent(ParentBean parentNew)
{
this.parent = parentNew;
if (this.pk == null)
{
this.pk = new ParentToChildPK ();
}
if (parentNew != null)
{
this.pk.setParentId(parentNew.getId());
}
else
{
this.pk.setParentId(null);
}
}
@ManyToOne
@JoinColumn(name="CHILDID", insertable=false, updatable=false)
public ChildBean getChild()
{
return this.child;
}
public void setChild(ChildBean childNew)
{
this.child = childNew;
if (this.pk == null)
{
this.pk = new ParentToChildPK ();
}
if (childNew != null)
{
this.pk.setChildId(childNew.getId());
}
else
{
this.pk.setChildId(null);
}
}
}
The embedded id (with annotation "@javax.persistence.EmbeddedId") is a member variable now and has getter and setter. Those are private for the same reasons as in the above sample.
The relationship fields don't change. But the setter for "child" and "parent" are more complex now, because they have to write the new ID to the embedded id class, and this primary key class variable maybe has to be created first.
But anyway, less code has to be written, and there are no duplicate fields (which would be fatal, if a field was renamed and only one variable was changed).
--------------------------------------------------------------
Comment by going to Community
[http://community.jboss.org/docs/DOC-13222]
Create a new document in EJB3 at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=102&co...]
13 years, 9 months
[EJB3] - EJB3 Plugin enhancement
by Administrator Administrator
Administrator Administrator [http://community.jboss.org/people/admin] modified the document:
"EJB3 Plugin enhancement"
To view the document, visit: http://community.jboss.org/docs/DOC-14251
--------------------------------------------------------------
h1. Overview:
This document is a detailed discussion on how the EJB3 Plugin should work against the JBoss Application Server, to allow EJB3 container configurations and EJB3 container components to be pushed in the AS.
h1. Terms:
Package - The word "package" in this document refers to a EJB3 component/module. Simply put, it can be considered as a jar file generated by the EJBTHREE project.
EJB3 - Unless specified, the use of EJB3 in this documentation refers to the JBoss EJBTHREE project (i.e. combination of both EJB3.0 and EJB3.1). EJB3.0 will specifically be used wherever appropriate. Same is the case with EJB3.1
h1. Current State:
- EJB3 Installer (org.jboss.ejb3:jboss-ejb3-installer) : Until very recently, the jboss-ejb3-installer used to dictate which packages/files from the EJB3 project are patched into the AS. However, recently starting version 1.0.3 of jboss-ejb3-installer, the responsibility of specifying the packages/files to be patched into the AS was delegated to the EJB3 plugin component.
- EJB3 Plugin (org.jboss.ejb3:jboss-ejb3-plugin) : The EJB3 Plugin decides which packages and what versions of those packages are installed into the AS. Currently driven through a package-list.txt http://anonsvn.jboss.org/repos/jbossas/projects/ejb3/trunk/plugin/src/mai...: http://anonsvn.jboss.org/repos/jbossas/projects/ejb3/trunk/plugin/src/mai...:
jboss-ejb3-timerservice-spi.xml
jboss-ejb3-endpointdeployer.xml
jboss-ejb3-endpoint.xml
jboss-ejb3-metrics-deployer.xml
Each of these .xml files in the package-list.txt are build files responsible for patching the AS with the corresponding package. These build files have an "install" and "uninstall" targets which are invoked by the EJB3 Installer. The "install" target is responsible for doing the necessary work to install the package. The "uninstall" as the name suggests is responsible for uninstalling the package.
Note: The "uninstall" part isn't fully tested. For the rest of the document, the main emphasis will be on "install" of packages. Once we have a clear understanding on how that is to be done, we will be considering the "uninstall" on similar lines.
Here's an example of what the "install" target looks like in each of these package installation build files:
<target name="install">
<copy file="lib/jboss-ejb3-endpoint.jar" todir="${jboss.home}/common/lib" verbose="${verbose}"/>
</target>
h1. Future:
- The EJB3 installer's (jboss-ejb3-installer) sole responsibility would be to install EJB3 packages into the AS. It will *not* decide which packages have to be installed. The EJB3 plugin (see next) will decide which ones are to be fed to the installer so that the installer just installs them.
- The EJB3 Plugin will provide a set of EJB3 packages to be installed into the AS. It will use the EJB3 installer to get these installed into the AS.
h1. Related JIRA:
EJBTHREE-1939 https://jira.jboss.org/jira/browse/EJBTHREE-1939 https://jira.jboss.org/jira/browse/EJBTHREE-1939
As part of EJBTHREE-1939, we plan to allow the EJB3 plugin to be able to:
1) Allow users to opt for the regular EJB3.0 bug fixes that come in from the current EJB3 plugin against AS-5
2) Allow users to opt for EJB 3.1 features through the plugin against AS-5
h1. Finer (implementation) details:
h2. EJB3 Plugin and Installer interaction:
As mentioned earlier, the installer will just install the packages that are fed to it by the Plugin. In it's simplest form (which has been implemented as a POC for EJBTHREE-1939) the installer will expect a "packages.xml" build file from the EJB3 Plugin. The packages.xml is expected to be a build file which contains an "install" and an "uninstall" target. The EJB3 installer will just trigger an "install" on this packages.xml and leave the rest of installation to this packages.xml implementation. Same would be the case with "uninstall".
>From the packages.xml "install" point of view, it would internally install each of the packages that form the corresponding runtime (EJB3.0 or EJB3.1). To do this, it would look for *-package.xml file within a pre-defined "packages" folder within the EJB3 Plugin jar
h2. Responsibility of each package:
Each package that forms a part of the EJB3 container is responsible for providing a *-package.xml file. The *-package.xml is expected to be an ant build file which will contain "install" and "uninstall" targets. For example, the jboss-ejb3-nointerface will contain a jboss-ejb3-nointerface-package.xml file (just an example):
<target name="install">
<copy file="lib/jboss-ejb3-nointerface.jar" todir="${jboss.home}/common/lib" verbose="${verbose}"/>
</target>
Since these *-package.xml files are meant for installation of the packages, these xmls should not make it to the runtime of the AS. Hence these should be placed in the src/main/assembly folder of the project component. For example, EJB3_TRUNK/nointerface/src/main/assembly/jboss-ejb3-nointerface-package.xml. The later section(s) discuss how this src/main/assembly/*-package.xml files are handled during the build of the Plugin.
h2. Maven Profiles:
To map these requirements which what we have discussed so far in this wiki - the EJB3 plugin in co-ordination with the EJB3 installer should be able to install packages that collectively form a "EJB3.0 implementation" and/or "EJB3.1 implementation". In Maven terms, let's consider each of this as a "profile". So the EJB3 plugin will now have a new profile for EJB3.1 (named EJB3_1). The earlier default profile would continue being specific to EJB3.0 implementation. The EJB3.1 profile will be a superset of EJB3.0 (default) profile. Each profile will be responsible for declaring the packages that this profile is dependent on to form the profile. The common dependencies for EJB3.0 and EJB3.1 will be provided by the default profile since EJB3.1 is an extension of EJB3.0. Any specific package dependency for EJB3.1 (ex: jboss-ejb3-nointerface) will be made available through the EJB3_1 profile. Here's an example from the jboss-ejb3-plugin pom.xml (work-in-progress):
<profiles>
<profile>
<!-- Profile for EJB 3.1 features to be delivered through the Plugin -->
<id>EJB3_1</id>
...
<!-- Dependencies for EJB 3.1 features -->
<dependencies>
<dependency>
<groupId>org.jboss.ejb3</groupId>
<artifactId>jboss-ejb3-nointerface</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
</profiles>
Notice that this EJB3_1 profile contains only EJB3.1 specific package dependencies - jboss-ejb3-nointerface being one of them. The rest of the common package dependencies like EJB3 core comes from the default profile.
h2. Assembling "packages" by the EJB3 Plugin:
The final output of the EJB3 Plugin would be a .jar file containing one "packages.xml" file and multiple *-package.xml files in a pre-defined folder within the jar (let's assume the folder name is "packages"). Each profile is responsible for providing the right set of *-package.xml files in the packages folder of this plugin jar. For example, the EJB3.0 profile will provide *-package.xml files which form the EJB3.0 implementation. It will *not* provide any EJB3.1 specific packages (*-package.xml files). On the other hand, the EJB3.1 profile will bring in the EJB3.1 related packages (Note that this would implicitly mean, EJB3.1 profile would bring in EJB3.0 *-package.xml since EJB3.1 is an extension of EJB3.0). Here's how the EJB3.0 plugin jar would look (just the relevant parts):
jboss-ejb3-plugin.jar
|
|--- packages
| |
| |--- jboss-ejb3-endpoint-package.xml
| |--- jboss-ejb3-endpoint-deployer-package.xml
| |--- jboss-ejb3-metrics-deployer-package.xml
| |--- jboss-ejb3-timerservice-package.xml
The EJB3.1 would look like:
jboss-ejb3-plugin-ejb31.jar
|
|--- packages
| |
| |--- jboss-ejb3-endpoint-package.xml
| |--- jboss-ejb3-endpoint-deployer-package.xml
| |--- jboss-ejb3-metrics-deployer-package.xml
| |--- jboss-ejb3-timerservice-package.xml
| |--- jboss-ejb3-nointerface-package.xml
The EJB3 plugin component would be responsible for generating the correct set of packages during build time. In it's current state (the work-in-progress patch for EJBTHREE-1939), it will use the maven-assembler-plugin http://maven.apache.org/plugins/maven-assembly-plugin/ http://maven.apache.org/plugins/maven-assembly-plugin/ to create these package assemblies. The EJB3.0 (default) profile will use the EJB3_TRUNK/plugin/src/main/assembly/ejb3-installer.xml to create the relevant set of plugin.jar/packages/*-package.xml files:
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/assembly-1.0.0.xsd"
>
<id>installer</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<componentDescriptors>
<!-- Common components required both in EJB3 and EJB3.1 -->
<componentDescriptor>src/main/assembly/ejb3-installer-components.xml</componentDescriptor>
</componentDescriptors>
</assembly>
The common components assembly descriptor file:
<?xml version="1.0" encoding="UTF-8"?>
<component>
<fileSets>
<fileSet>
<directory>src/main/resources</directory>
<includes>
<!-- The *-package.xml files -->
<include>jboss-ejb3-timerservice-spi-package.xml</include>
<include>jboss-ejb3-endpointdeployer-package.xml</include>
<include>jboss-ejb3-endpoint-package.xml</include>
<include>jboss-ejb3-metrics-deployer-package.xml</include>
<include>setup.xml</include>
<include>packages.xml</include>
</includes>
<outputDirectory>packages</outputDirectory>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputFileNameMapping></outputFileNameMapping>
<unpack>true</unpack>
<includes>
<include>org.jboss.ejb3:jboss-ejb3-installer</include>
<include>org.jboss.ejb3:jboss-ejb3-common</include>
</includes>
</dependencySet>
<dependencySet>
<outputFileNameMapping>${artifactId}.${extension}</outputFileNameMapping>
<includes>
<include>ant-contrib:ant-contrib</include>
<include>org.jboss.ejb3:jboss-ejb3-cache:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-common:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-core:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-deployers:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-endpoint:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-endpoint-deployer:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-ext-api:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-ext-api-impl:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-interceptors:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-metadata:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-mc-int:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-metrics-deployer:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-proxy-impl:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-proxy-spi:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-proxy-clustered:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-security:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-timerservice-spi:jar</include>
<include>org.jboss.ejb3:jboss-ejb3-transactions:jar</include>
</includes>
<outputDirectory>lib</outputDirectory>
</dependencySet>
<dependencySet>
<outputFileNameMapping>${artifactId}.${extension}</outputFileNameMapping>
<includes>
<include>org.jboss.ejb3:jboss-ejb3-endpoint-deployer:jar</include>
</includes>
<outputDirectory>deploy</outputDirectory>
</dependencySet>
<dependencySet>
<outputFileNameMapping>${artifactId}-${classifier}.${extension}</outputFileNameMapping>
<includes>
<include>org.jboss.ejb3:jboss-ejb3-common:jar:client</include>
<include>org.jboss.ejb3:jboss-ejb3-core:jar:client</include>
<include>org.jboss.ejb3:jboss-ejb3-proxy-impl:jar:client</include>
<include>org.jboss.ejb3:jboss-ejb3-proxy-spi:jar:client</include>
<include>org.jboss.ejb3:jboss-ejb3-proxy-clustered:jar:client</include>
<include>org.jboss.ejb3:jboss-ejb3-security:jar:client</include>
</includes>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
</component>
And finally, the EJB3.1 specific assembly file:
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/assembly-1.0.0.xsd"
>
<id>ejb31-installer</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>src/main/resources</directory>
<includes>
<!-- EJB3.1 specific *-package.xml file(s) -->
<include>jboss-ejb3-nointerface-package.xml</include>
</includes>
<outputDirectory>packages</outputDirectory>
</fileSet>
</fileSets>
<componentDescriptors>
<!-- Common EJB3.0 and EJB3.1 packages -->
<componentDescriptor>src/main/assembly/ejb3-installer-components.xml</componentDescriptor>
</componentDescriptors>
<dependencySets>
<dependencySet>
<!-- EJB3.1 specific libraries -->
<outputFileNameMapping>${artifactId}.${extension}</outputFileNameMapping>
<includes>
<include>org.jboss.ejb3:jboss-ejb3-nointerface:jar</include>
</includes>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
Each of the Maven profile in the EJB3 plugin pom would then refer to the appropriate assembly descriptor file to create the packages for installation. For example, the EJB3_1 profile would use the following maven-assembly-plugin configuration:
<profile>
<!-- Profile for EJB 3.1 features to be delivered through the Plugin -->
<id>EJB3_1</id>
<build>
<plugins>
<!-- Assembly Plugin -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-1</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptors>
<!-- Use the EJB 3.1 installer descriptor -->
<descriptor>src/main/assembly/ejb31-installer.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>org.jboss.ejb3.installer.Installer</mainClass>
</manifest>
</archive>
</configuration>
<inherited>false</inherited>
</plugin>
</plugins>
</build>
...
And the EJB3.0 (default) profile would use:
<descriptors>
<!-- Use the EJB 3.0 installer descriptor -->
<descriptor>src/main/assembly/ejb3-installer.xml</descriptor>
</descriptors>
h2. Plugin creation:
At build time, we decide which plugin we want to create. Either EJB3.0 (by default) or EJB3.1. For EJB3.1 plugin generation, use the following command:
mvn clean install -P EJB3_1
h1. TODO:
1) This is just an initial draft, more will be discussed in this wiki or the EJB3 dev forum
2) The implementation suggestions mentioned above, do not break any backward compatibility of the Plugin or the Installer.
--------------------------------------------------------------
Comment by going to Community
[http://community.jboss.org/docs/DOC-14251]
Create a new document in EJB3 at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=102&co...]
13 years, 9 months
[EJB3] - AccessEJBsRemotely
by Administrator Administrator
Administrator Administrator [http://community.jboss.org/people/admin] modified the document:
"AccessEJBsRemotely"
To view the document, visit: http://community.jboss.org/docs/DOC-9047
--------------------------------------------------------------
h2. How do I access EJBs remotely
h3. JNDI Properties
h4. Using a Provider URL
You'll need a jndi.properties on the remote client which looks like this:
#jboss JNDI properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jnp.interfaces
### The TimedSocketFactory connection timeout in milliseconds (0 == blocking)
jnp.timeout=0
### The TimedSocketFactory read timeout in milliseconds (0 == blocking)
jnp.sotimeout=0
Replace localhost with the jboss's DNS name or IP and if you have configured the jboss naming service for some other port, you will need to change the 1099 to reflect that port. You can also provide a delimited list for the provider URL like java.naming.provider.url=jnp://192.168.99.1:1100,192.168.99.2:1100,192.168.99.3:1100
The last two timeout properties are optional, defaults are zero.
h4. Using Naming Discovery
If you would like to use Naming Discovery (appropriate for a clustered environment), you will need a jndi.properties on the remote client which looks like this:
#jboss JNDI properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=
java.naming.factory.url.pkgs=org.jnp.interfaces
jnp.partitionName=YourPartitionName
This configuration presupposes that your network is set up in such a way that multicast traffic is visible between your remote client and the EJB-serving JBoss instance. (e.g. the machines are on the same subnet) It also assumes that you have http://community.jboss.org/docs/DOC-10386 configured your serving JBoss instance to be a member of the
YourPartitionName
partition.
h3. Interfaces
You must use Remote and RemoteHome interfaces.
h3. Security
If you have configured a secure realm, you will need to set up a JAAS security login to the EJB tier.
--------------------------------------------------------------
Comment by going to Community
[http://community.jboss.org/docs/DOC-9047]
Create a new document in EJB3 at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=102&co...]
13 years, 9 months