Doing parallel processing in EJB containers before EJB 3.1 was a pain in the ass. You have to fiddle around with JMS and Message Driven Beans.
EJB 3.1 introduces asynchronous method calls and simplified the management of concurrently running tasks a lot. I found two pretty good examples how to use asynchronous method calls:
http://satishgopal.wordpress.com/2011/04/24/ejb-3-1-asynchronous-methods/
http://docs.oracle.com/javaee/6/tutorial/doc/gkkqg.html
Total Pageviews
Showing posts with label ejb. Show all posts
Showing posts with label ejb. Show all posts
Tuesday, July 10, 2012
Friday, January 20, 2012
Iterating over result list from a JPA query
Sometimes when using EJB 3.x, it is necessary to use JPA QL or SQL native queries to fetch objects from the database. It might be used to achieve better performance or to just fetch a particular set of attributes of the object but not the complete object with all its dependencies.
There's is even the possibility to avoid casting completely by using a constructor expression with the appropriate arguments in the SELECT section:
Remember to declare the appropriate constructor.
There's one thing you have to keep in mind when doing this: The result list containing the object will be an array of objects!
"The SELECT clause queries more than one column or entity, the results are aggregated in an object array (Object[]) in the java.util.List returned by getResultList( )"
Working example:
Query query = manager.createQuery("SELECT v1.bitbit, v1.numnum, v1.someTime, t1.username, t1.anotherNum FROM MasatosanTest t1 JOIN MasatoView v1 ON v1.username = t1.username;");
List results = query.getResultList( ); // Fetches list containing arrays of object
Iterator it = results.iterator( );
while (it.hasNext( )) {
Object[] result = (Object[])it.next(); // Iterating through array object
Boolean first = (Boolean) result[0]; // Fetching the field from array
/* Likewise for all the fields, casting accordingly to the sequence in SELECT query*/
}
There's is even the possibility to avoid casting completely by using a constructor expression with the appropriate arguments in the SELECT section:
SELECT new org.somepackage.XEntity(x.a, x.b) FROM XEntity x
Remember to declare the appropriate constructor.
The code fragments and the solution in this blog post was taken from this question on stackoverflow.
Saturday, June 27, 2009
Testing your EJB3 beans in an embedded EJB container using OpenEJB with Maven as build system
Intro
I am currently working on a private project implementing a web application using GWT as frontend and EJB3 as backend technology.Testing my EJB3 beans using JUnit4 turned out to be very complicated. I had to manually inject all the required resources like EntityManager, EntityManagerFactory and all EJB3 beans the bean under test uses.
This may work for a simple project with a few beans but this will definitely not work for a huge project.
So I was looking for a better and less complicated way to test my beans.
Embedded Glassfish came to my mind, but this project isn't final yet, so I stumbled across a blog entry of Adam Bien's blog where he talks about OpenEJB and I thought just give it a try.
I use Maven as build system for all my projects so everything below this line just fits for Maven. If you use Ant or something different you may have to do other things to set up your testing environment.
Maven configuration
Using the OpenEJB embedded container is very easy. Just add the following dependency to your POM:<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-ejbd</artifactId>
<version>3.1.1</version>
<scope>test</scope>
</dependency>
In my case it turns out that the dependency activeio-core version 3.0.0-incubator is not hosted in any publicly available maven repository (well at least not in those I use). So I grabbed it from here and pushed it into my running Nexus instance.
In case you use OpenJPA as your persistence provider you have to configure the Maven surefire plugin to use the OpenEJB Java Agent. This is described in detail on this OpenEJB site.
Necessary files
My project consists of three maven modules:- project-entities (contains all JPA entities and the production persistence.xml under src/main/resources/META-INF)
- project-api (contains all session beans and services)
- project-webapp (the GWT web application)
Because I only work with annotations this file is nearly empty in my case. It just contains the following line:
<ejb-jar/>
In case you have configured a persistence.xml file under src/test/resource/META-INF of your module under test (in my case project-api) using RESOURCE_LOCAL I recommend to delete this file completely. In my case this file was interfering with the OpenEJB setup and all my beans were not deployed into the embedded container. Hence, my embedded tests were not working.
Configuring the OpenEJB embedded container for testing
Now it's time to configure the OpenEJB embedded container. This can be done in two ways. I will only explain the configuration in a JUnit base test class, so this can be used by all unit tests deriving from this class. There is another way in configuring the container using an XML file. Please consult the OpenEJB website for further details.Like I said before, I am using Hibernate as persistence provider. The setup of the embedded container is done in a method annotated with the JUnit annotation @Before, so it get's called before a test is executed. You may wish to change this in a way it better fits into your environment (using @BeforeClass, etc ...)
@Before
public void initializeEmbeddedContainer() throws Exception {
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.openejb.client.LocalInitialContextFactory");
....
....
....
context = new InitialContext(properties);
}
In the above code snippet the bold lines are important. They are responsible for starting the embedded container. There are a few more properties you have to set to get the embedded tests running. Now you have to override the settings you made in your persistence.xml for running in OpenEJB.
The following lines will do that for you:
properties.put("puName", "new://Resource?type=DataSource");
properties.put("puName.JdbcDriver", "org.hsqldb.jdbcDriver");
properties
.put("puName.JdbcUrl", "jdbc:hsqldb:mem:testdatabase");
properties.put("puName.hibernate.dialect",
"org.hibernate.dialect.HSQLDialect");
properties.put("puName.hibernate.hbm2ddl.auto", "update");
properties.put("puName.hibernate.show_sql", "true");
properties.put("puName.hibernate.format_sql", "true");
puName stands for persistence unitname. Please replace this with the real name of your persistence unit. The lines in bold are necessary. I am using HSQL DB, but this should work with any JDBC database. Don't forget to let Hibernate create the DB schema for you, otherwise your tests will fail because of non existent tables.
There is just another configuration property you may want to use: Restarting the OpenEJB embedded container between tests to avoid strange side effects in your tests. This is done by setting the property:
properties.put("openejb.embedded.initialcontext.close", "destroy");
But be aware that this property is an undocumented feature and may change in further versions of OpenEJB. This Jira entry recommends to achieve the same effect in configuring the maven surefire plugin.
So the complete method to initialize your in-container tests will look like this:
@Before
public void initializeEmbeddedContainer() throws Exception {
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.openejb.client.LocalInitialContextFactory");
properties.put("puName", "new://Resource?type=DataSource");
properties.put("puName.JdbcDriver", "org.hsqldb.jdbcDriver");
properties
.put("puName.JdbcUrl", "jdbc:hsqldb:mem:testdatabase");
properties.put("puName.hibernate.dialect",
"org.hibernate.dialect.HSQLDialect");
properties.put("puName.hibernate.hbm2ddl.auto", "update");
context = new InitialContext(properties);
}
Setting up a unit test
The last thing to do now is getting your beans from the embedded container. This can be done in two ways. One way is to use a special OpenEJB annotation to inject the bean into your test class. As this is an elegant way I prefer to code this with plain old Java method calls using JNDI lookup, because the first solution will make your code depend on OpenEJB API.This is how it works with local EJBs:
IServiceLocal localService = (IServiceLocal) getContext().lookup(ServiceImplLocal);
where IServiceLocal is the local interface of the session bean and ServiceImplLocal is the JNDI name of the bean implementation. The OpenEJB standard JNDI name for beans is {deploymentId}{interfaceType.annotationName}.
The deploymentId is the name of the EJB implementation (in our case ServiceImpl) and the interfaceType is Local, because the EJB under test is a local EJB.
Running your tests
Simply callmvn clean test
Thursday, February 08, 2007
Timer problems in JBoss with TimerBeans
Since I updated to JBoss 4.0.4.GA I randomly receive the following execption in one of my applications:
23:22:19,812 ERROR [TimerServiceImpl] Cannot create txtimer
java.lang.IllegalStateException: Unable to persist timer
at org.jboss.ejb.txtimer.DatabasePersistencePolicy.insertTimer(DatabasePersistencePolicy.java:126)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
at org.jboss.mx.server.Invocation.invoke(Invocation.java:86)
at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
at org.jboss.mx.util.MBeanProxyExt.invoke(MBeanProxyExt.java:210)Caused by: java.sql.SQLException: Unique
constraint violation: in
statement [insert into TIMERS
(TIMERID,TARGETID,INITIALDATE,TIMERINTERVAL,INSTANCEPK,INFO) values
(?,?,?,?,?,?)]
at org.hsqldb.jdbc.Util.throwError(Unknown Source)
at org.hsqldb.jdbc.jdbcPreparedStatement.executeUpdate(Unknown Source)
at org.jboss.resource.adapter.jdbc.CachedPreparedStatement.executeUpdate(CachedPreparedStatement.java:95)
at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:251)
at
It turns out to be a problem with a TimerBean.
A solution is described in the JBoss JIRA: http://jira.jboss.com/jira/browse/JBAS-3380
To make is short:
The "localDB.script" file ($JBOSS_INSTALL_DIR/server/default/data/hypersonic) must be cleaned up by deleting all (or the particular) timer entries (INSERT INTO TIMERS ...). Those entries are inserted by JBoss and represent timers which should be executed after a server crash. Unfortunately the ID generator for inserting unique timer ids doesn't generate unique ids :-(
Thursday, June 15, 2006
Moving towards JBoss 4.0.4.GA
I decided to upgrade my JBoss 4.0.3.SP1 to the newest version 4.0.4.GA. I am only interested in the EJB3 container so I have chosen to use the installer package to download.
The installation is quiet easy using the installer. Just simply choose the EJB3 container and everything gets installed. But the hardest part is still in front of us.
My client application fails with different exceptions communicating with the server. Argh!! Yes of course, I had to update my jboss client libraries. So here is the list of necessary libraries to update:
The installation is quiet easy using the installer. Just simply choose the EJB3 container and everything gets installed. But the hardest part is still in front of us.
My client application fails with different exceptions communicating with the server. Argh!! Yes of course, I had to update my jboss client libraries. So here is the list of necessary libraries to update:
- jboss-j2ee
- jboss-ejb3x
- jboss-ejb3
- jboss-annotations-ejb3
- jboss-aspect-library-jdk50
- jbossall-client
- jboss-aop-jdk50-client
Subscribe to:
Posts (Atom)