Debugging Field Injection With NetBeans - Another Reason To Delete Setters

Java EE fully supports field injection:


@Stateless
public class LegacyDataSourceConsumer {
    @Inject @Legacy
    DataSource ds;
}

You can inject resources, EJBs or CDI managed beans directly into fields since Java EE 5 and so for about 5 years. Setters or specific "injector" methods are optional. With NetBeans you can easily debug the injection with a field breakpoint. You only have to click on the grey bar left the editor to enable a field breakpoint. You should see a triangle:

By clicking on the triangle and choosing Field Breakpoint -> Properties you can setup additional behavior. The default behavior "Stop On: Field Access Or Modification" is perfect for Dependency Injection debugging. The current thread will stop (probably in a business method) at injection time. So: delete your setters and enjoy Java EE :-).

Comments:

Hi Adam

I agree that setters are the boilerplate code. But without setters it is hard to provide mocks in your tests :-( How do you set mocks in the tests when the setters are missing?

Thanks,
Marcin

Posted by Marcin on January 24, 2011 at 11:52 AM CET #

@Marcin,

interfaces are no more (>5 years) necessary for mocking: http://www.adam-bien.com/roller/abien/entry/will_ejb_3_1_ioc

Setters + Interfaces makes actually testing harder...:-)

adam

Posted by adam-bien.com on January 24, 2011 at 12:05 PM CET #

Yeah, you can mock classes, correct. But how do you set these mock in your beans or whatnots that don't have setters? The only other way it to use constructor injection (not always an option), or use reflection, or use some dependency injection framework (which uses reflection under the hood). How does this correspond to your idea of testability?

Posted by ucilala on January 25, 2011 at 03:48 PM CET #

@Ucilala,

your question is already answered - with code: http://www.adam-bien.com/roller/abien/entry/will_ejb_3_1_ioc :-)

thanks!,

adam

Posted by adam-bien.com on January 25, 2011 at 08:59 PM CET #

Hi Adam, I really like your blog and your Ideas. I saw you in JUG Darmstadt - you did a very good show!

Just to mention that eclipse also supports interception of field modifications since a couple of years. The idea is not new.

I don't like to hear that interfaces are dead or should be dead. For some things they may not make sense at all. But Interfaces are a really good way to point out what kind of capabilities a class supports and what is needed to replace a certain functionality.

Posted by Michael Kirchmann on January 25, 2011 at 11:13 PM CET #

Not really, no it isn't. Or I didn't find the answer.
As you seem to misunderstood my question, let me put it in code:

@Stateless
public class EJBean {
@Inject
private CDIBean cdi;

public void bar(int i) {
if (i == 17) {
cdi.foo(i);
}
}
}

How do I test EJBean with a mock CDIBean (it can be an interface or a non-final class, aggreed), to, say, check if CDIBean.foo(int) was called for EJBean.bar(17)?

You can't, unless you use reflection (yuck!), constructor injection (not always an option), or employ a standalone CDI container (like Weld with Weld SE) plus a @Alternative - but this is no longer a unit test, no it isn't.

And please don't tell me that I don't unit test EJBs, that's exactly why this whole 'EJB3.x is POJO' is about - to be able to use them outside the container, and test.

Posted by ucilala on January 25, 2011 at 11:18 PM CET #

@Ucilala - thank you for better description of my doubts about missing setters.

@Adam - how to inject mock to unit tests without setters? I don't like to use embeded container for unit tests.

Thanks,
Marcin

Posted by Marcin on January 26, 2011 at 11:51 AM CET #

@Marcin
change
@Inject
private CDIBean cdi;
to
@Inject
//protected for tests
protected CDIBean cdi;

pretty much standard for test

Posted by Nils on January 26, 2011 at 12:01 PM CET #

I use EasyMock + Unitils to test my EBJs. Unitils provides an easy way, with @InjectIntoByType, to inject my Mocks

Posted by Fabricio Lemos on January 27, 2011 at 09:37 PM CET #

AFAIK "break on modification" can not catch the cases when the modification is done trough reflection. I filed a bug with Eclipse last year and they said that it is a limitation of the JVM. I also just tried with Netbeans 6.9.1 with the same result (ie. when setting a field trough reflection, the breakpoint is not triggered).

So unless CDI container is not doing the injection trough reflection (it might create dynamic bytecode for performance reasons - I didn't look into it), I think that the triggering of your breakpoint is because you're accessing the field, not because the CDI container sets it.

Posted by Cd-MaN on February 04, 2011 at 01:34 PM CET #

Post a Comment:
  • HTML Syntax: NOT allowed
...the last 150 posts
...the last 10 comments
License