-
1. Re: EJB and CDI internals
nickarls Jan 25, 2013 1:43 AM (in response to rcd)The component models are a bit blurred now (since JSF has their own managed beans and hopefully JAX-RS doesn't add to the mix in the next EE rev) but hopefully they move towards a more unified model with the managed bean specification.
EJBs can exist without CDI (obviously) and CDI can exist without EJBs (POJOs). When they are used together (e.g @SessionScoped @Stateful) you get a small CDI proxy that wraps the EJB and provides e.g. decorators, lifecycle management and the other stuff.
I would go for EJB + CDI in most cases. A local-interface-only EJB is not that heavy and the transaction benefits it brings are nice. Of course you don't have to use EJB for everything, POJOs are fine for helper classes that don't persist etc. As for performance, if you run e.g.
a JSF web app, the time spent constructing the view is minimal compared to the extra CDI-EJB proxies.
First it used to be "Java is soooo slow". Then it was "EJB is sooooo heavyweight".
-
2. Re: EJB and CDI internals
sfcoy Jan 25, 2013 8:10 AM (in response to rcd)Your co-worker is not "keeping up" at all.
One of the best places to catch up in a single location is Adam Bien's blog.
-
3. Re: EJB and CDI internals
rcd Feb 13, 2013 3:46 PM (in response to sfcoy)Nicklas, Stephen: thanks for your replies. I just conducted a not especially scientific test to guage the performance difference. Code included for anyone who wants to duplicate my test. If you just want to know the outcome, skip to the last line of this post.
First, I made an EJB:
{code}
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Singleton;
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class EJBPerfTester {
public void doStuff() {
long total = 0;
for (int i = 0; i < 1000000; i++) {
total += i;
}
System.out.println("total is " + total);
}
}
{code}
Then I made a roughly equivalent CDI bean:
{code}
@ApplicationScoped
public class CDIPerfTester {
@Inject
private UserTransaction tx;
public void doStuff() {
try {
tx.begin();
long total = 0;
for (int i = 0; i < 1000000; i++) {
total += i;
}
tx.commit();
System.out.println("total is " + total);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
{code}
Note that the EJB has bean-managed concurrency, attempting to match the fact that CDI doesn't manage concurrency. The EJB does have default transaction semantics, so the CDI bean explicitly starts and commits a transaction to match. The EJB is a singleton while the CDI bean is application scoped, so they are roughly the same in that area as well. Both do the exact same "work" of adding up a bunch of numbers and printing the result.
Then I have a JSF bean, into which the two beans are @Inject'ed, with some XHTML to invoke them. That's not especially important as these beans could be invoked in any number of ways, and the timing code explicitly attempts to minimize the influence of anything else:
{code}
Stopwatch sw = new Stopwatch();
sw.start();
ejbTester.doStuff();
sw.stop();
long ejbTime = sw.elapsedTime(TimeUnit.MICROSECONDS);
sw.reset();
sw.start();
cdiTester.doStuff();
sw.stop();
long cdiTime = sw.elapsedTime(TimeUnit.MICROSECONDS);
L.infov("EJB Time: {0} us, CDI Time: {1} us, Difference: {2} us", ejbTime, cdiTime, ejbTime - cdiTime);
{code}
The stopwatch is from Google Guava, the logger is JBoss Logging, not that the latter makes much difference as you could just use a System.out.println() there.
You might notice I'm measuring the time in microseconds. That is because the difference in performance is not discernable at the millisecond level. On my machine, if there is really a penalty for the EJB, it is at most 140 microseconds. I say "if there is really a difference" because there appear to be some other factors influencing the timings, despite my best efforts. For example, if I switch the order of the invocations, and run the CDI bean first, the difference hovers around 20 microseconds instead of 140, despite the fact that everything else is exactly the same.
Regardless, a tenth of a millisecond (again, assuming that's not caused by something else) is an incredibly tiny amount of overhead. So for anyone else out there who's wondering about EJB vs CDI performance: it appears there is effectively no difference on AS7.