EJB 3.0 - What's wrong with @Inject?

Discussions

News: EJB 3.0 - What's wrong with @Inject?

  1. EJB 3.0 - What's wrong with @Inject? (59 messages)

    Adrian Colyer (AspectJ lead) has written a nice piece on the new @Inject annotation that was mentioned in the EJB 3 talk at the symposium. There are many good points, which apply to annotations in general. I specifically like the notes: remember this is about metadata, and annotations should be adjectives/adverbs.

    Excerpt
    There are two separate issues raised here - why do I need the @Inject annotation at all, and if I do need an annotation, is @Inject the right one? Like it or not, annotations are coming. A prominent J2EE specification such as EJB should guide us in their correct usage, and not set a bad example. This morning it fully dawned on me why I think @Inject is a bad example, and it's based on the same reasoning we give for how we think annotations will be best used in conjunction with an aspect-oriented language like AspectJ.

    The clue is in the name: "JSR 175: A metadata facility for the Java Programming Language." Annotations are supposed to be metadata - they are supposed to provide information about the language element being annotated: a good annotation describes some property of the thing it is annotating. If classes and data members are nouns, and methods are verbs, then annotations are like adjectives and adverbs, describing the classes, fields, and methods respectively. But "inject" isn't an adverb or adjective - it's a verb. "Inject" doesn't describe any property of the set-method, instead it sounds more like a compiler or run-time directive. That's not a good way to encourage people to think about annotations, though I'm sure we'll see many such abuses in time. The smallest possible change that would make me happier is to add two characters, "ed." That would give us the annotation @Injected, which does at least describe a property of the dependency (it's an injected dependency).
    Read Adrian Colyer in EJB 3.0 - What's wrong with @Inject?

    Threaded Messages (59)

  2. @Apparent :)[ Go to top ]

    I just have one thing to say: when the solution is right it is apparent :)
  3. @Apparent :)[ Go to top ]

    I think it is more usefull to let configure and to register components.

    class MyAppLifeCycleListener implements AppLifeCycleListener{


      void init(Server server){
      
       server.registerSessionBean( new MyBean(server.lookup("myDatasource")) );
       server.registerMessageBean( ProxyFactory.newProxyInstance( new MyMSGBean() ) );
       ............
       loadSomeExoticXMLAndInjectDependancies("myApp.xml",server);

      }

      void destroy(){
        stopMyThreads();
        clearCashe();
        dropConnections();
      }


    }


    Some "helper" can do the same as it does at this time, but I do not think IoC or "lookup" is the best way to configure stuff and I need to do it myself (I need to do more usefull stuff than dependany injection in this code too).
  4. Do we need @Inject?[ Go to top ]

    Why is there a need for any @inject tag? Why can't we just tell the container if you load a class and it needs a FooService (i.e. it has a setFooService(FooService) method), then give it the FooService you are managing. Sort of like "auto-wire" on steroids. After all, if there are any ambiguities (e.g. to beans of the type FooService), we are going to have to clarify the ambiguity anyway, through a config file (God forbid we use XML).

    I guess this is relinquishing a lot of control, but the majority of the time (at least in my experience with DI) this will be just fine. Although without explicit annotation/external config, there appears to be a little black magic going on behind the scenes.

    Ryan
  5. Adrian's adverb/adjective analogy is nice. I fully agree with him.

    Forcing people to use annotations as extra hints to the container is a bad idea.

    1) It is redundant, as the well-established Java Bean model for properties is enough.

    2) It is intrusive in the way that classes will have runtime dependencies on the associated annotation class.

    The common argument seems to be that @Inject is meant to be some sort of extra information to the container allowing it to differentiate between properties that should be injected by the container - and those that should not.

    This smells of design up-front to me. I have never heard of anyone wanting this kind of separation. -And if it is still needed, there are better ways to deal with it such as using a @NotInjected annotation or even better a way to tell the container to be pedantic - or not about unsatisfiable setters.

    Moreover, if the EJB3 spec goes for constructor injection , there would be no need for annotations whatsoever. What's declared in the constructor(s) is what the container has to provide. Period. And you can still have setters on the same class that would be ignored by the container.

    Aslak
  6. It is redundant, as the well-established Java Bean model for properties is enough.
    It is enough but it pollutes your Java type system, so annotations are a better way. Same for marker interfaces.
    This smells of design up-front to me. I have never heard of anyone wanting this kind of separation.
    JNDI names, datasources, JMS topics and queues... the examples are endless.
    What's declared in the constructor(s) is what the container has to provide. Period. And you can still have setters on the same class that would be ignored by the container.Aslak
    Are you suggesting I should add a constructor to my POJO that takes a datasource? A connection pool?

    Now that's what I call intrusive.

    Injection should have no impact on my business logic nor on my public or private API. With your suggestion, it will infect all my objects, which is exactly what we are trying to avoid.

    I know, it takes a little while to get used to and it's basically putting in question all kinds of practices that we have grown up with in Java. But once you put yourself in that mindset, you notice that we've been doing metadata for years, but we've been perverting the Java language to achieve that goal.

    JSR 175 is finally drawing a line in the sand and forcing us to split our POJO's in two distinct parts: business logic and metadata.

    --
    Cedric
  7. Are you suggesting I should add a constructor to my POJO that takes a datasource? A connection pool?Now that's what I call intrusive.
    Whether we use constructor based injection, or setter based injection it doesn't really matter that much in the greater scheme of things. I don't think anyones arguing for either approach here. (Constructors are easier as it provides a single point to validate that all the injections are correctly configured but hey setters work too, its just more work for the developer).

    I'm interested to hear what the actual point of @Inject is. i.e. why can't I just use a regular constructor or setter, like we've been using for years?

    James
  8. Are you suggesting I should add a constructor to my POJO that takes a datasource? A connection pool?
    Yes!

    Any field that is used by a class internally must be initialised somewhere in order to avoid NullPointerException. This includes DataSource, Connection, JMSTopic etc if that is what your POJO needs.

    The essential question here is what DI flavour is most explicit and simple to use. Consider this (using your example):
    class ConstructorInjected {
        private DataSource ds;

        public ConstructorInjected(DataSource ds) {
            this.ds = ds;
        }

        public void doIt() throws SQLException {
            Connection c = ds.getConnection();
            ...
        }
    }
    And how it is used from a JUnit test:
    public void testWithCI() {
        DataSource ds = null ...;
        ConstructorInjected ci = new ConstructorInjected(ds);
        ci.doIt();
    }
    Now that's what I call intrusive.
    I don't buy your argument that this is intrusive. Perhaps our understanding of the word is different. If your POJO needs a DataSource in order to work, that means it has a dependency on a DataSource. Are you suggesting that not providing your POJO with a DataSource - and then test it under those circumstances - would work? I cannot in my wildest imagination see how that would work. (I.e. avoid NPE in doIt()).

    By forcing the client of the class (unit test, container) to provide that dependency in the constructor you obtain two things:

    1) You are making the dependency explicit. (Makes things clear for the test writer).
    2) Your object is never in an indeterminate state. (Further eases testing).
    3) You don't need setters. (Less setup code in your tests).

    I don't see how @Inject wold make anything easier. Actually, I don't even see what problem @Inject is trying to solve. Please help me out here.
  9. It is very trivial to implement both ways at home and it is very easy to code this kind of infrastucture code. As more dicussions I see about IoC as more I am sure it is more about personal preferences. So why do I need a container if it can not satisfy my personal preferences and I can implement trivial things myself or use some open source library ?
  10. Are you suggesting I should add a constructor to my POJO that takes a datasource? A connection pool?
    Yes!
    The reason why it's not acceptable to me is because I can no longer write something like this (inspired from Hibernate):


    Account a = new Account();
    a.setOwner("Cedric");
    EntityManager em = ... // get the EM
    em.save(a);
    em.flush();


    Notice two things in this code:

    • It makes no reference to any deployment-time setting (such as a datasource)
    • It could be a unit test or business logic, there is no difference
    With your solution, I can no longer create my objects without "polluting" my code with deployment-time information. The point of this is to have this information injected, i.e., it will be provided elsewhere.

    Another reason why this is important is that this datasource might not even exist at the time this code is run. Maybe I am running in a smart container that will instantiate them lazily, only when they are used for the first time.

    In other words, materializing the datasource is a crosscutting concern, it should not be part of my business logic.

    --
    Cedric
  11. The reason why it's not acceptable to me is because I can no longer write something like this (inspired from Hibernate):
    Account a = new Account();
    a.setOwner("Cedric");
    EntityManager em = ...// get the EM
    em.save(a);
    em.flush();
    This confuses me a bit. Who needs the data source again? The Account or the Entity Manager? I am assuming the latter, since it looks like the EM is handling the persistence and the Account is a domain object independent of any persistence strategy.

    If you did intend for the Account to have a reference to the DS, my question would be why?

    In Spring, here is how you would do this in any deployment environment _today_ (assuming the EntityManager is analagous to a Hibernate 'Session' ;-))

    - Configure a "factory bean" which takes as input ORM configuration information and encapsulates the creation of a Hibernate SessionFactory. In your example, the location of the Account ORM metadata and the data source implementation to use would be injected as configuration properties.

    - The factory bean will produce a properly configured SessionFactory when requested, which can then be passed around to DAOs that provide data access. These DAO clients are kept independent of the factory bean and how the SessionFactory itself was assembled. They are abstracted away from the low-level DataSource entirely.

    As a result in code, this makes code as simple as:

    Account a = new Account();
    a.setOwner("Cedric");
    Session session = getSession();
    session.save(a);
    session.flush();

    Looks similiar! :-)
  12. This confuses me a bit. Who needs the data source again? The Account or the Entity Manager?
    Right, DataSource is probably not the best example in this particular case.

    Replace it with one of the following:

    • A JMS topic/queue, where your object will post a message
    • An Environment object, which has been initialized externally by the container
    • An EntityContext, which could give you access to the transaction context
    • etc...
    You get the idea.
    As a result in code, this makes code as simple as:Account a = new Account();a.setOwner("Cedric");Session session = getSession();session.save(a);session.flush();Looks similiar! :-)
    Absolutely, the mechanism of injection is the same and the programming model is inspired from Hibernate. I think we agree on how things work, it's just the way everything is specified is different.

    So far, the traditional way of wiring things together has been with external XML files and Java syntactic conventions or interfaces. What we are suggesting with EJB3 is to use annotations instead.

    --
    Cedric
  13. Cedric :
    Absolutely, the mechanism of injection is the same and the programming model is inspired from Hibernate. I think we agree on how things work, it's just the way everything is specified is different.So far, the traditional way of wiring things together has been with external XML files and Java syntactic conventions or interfaces. What we are suggesting with EJB3 is to use annotations instead.
    I don't understand how this would work if you aren't going to do magical things at instance creation. Going back to your example code, lets assume this POJO needs a resource (DS, JMS topic, etc)
    Account a = new Account();
    a.setOwner("Cedric");
    EntityManager em = ... // get the EM
    em.save(a);
    em.flush();
    Where does the container get to inject the dependencies? (At what time in the lifecycle of the object?)

    What if they are needed for setOwner()?

    If this happens at save() time, and I as the client aren't interested in how the POJO works, I'd have to resort to something like :

    Account a = new Account();
    EntityManager em = ... // get the EM
    em.save(a);
    a.setName("Cedric");
    em.save(a);

    to be sure that the POJO is functional. And you can imagine all the problems that pattern will cause..

    So why not just require a factory?

    Account a = (Account) em.new(Account.class);
    a.setName("cedric");
    em.save(a);
    em.flush();
  14. Where does the container get to inject the dependencies? (At what time in the lifecycle of the object?)
    From what I understand, the container intercept when new is done on an object and then inject the dependencies. (Using bytecode instrumentation I assume) Cedric/Gavin, is that right?

    Is there any official document concerning EJB 3.0? The slides from the sympodium, an early draft of the spec or something like that?

    Concerning the anotations, I see a lot of things I pontentially dislike, but without the whole picture, it's hard to judge. For example, you need annotations to specify that a setDataSource(DataSource) method is to be used to inject a datasource, if what happens if there's two datasource? Is the metadata just one option for DI, or is it mandatory?

    Also, assuming the above concerning the new is accurate, I see several potential problems with this approach. For example, what if you want two instances of the same class with different configurations? Also, if you have to use "new HibernateAccountDao()", then it makes is more difficult to "talk to interfaces", what if you want to switch to "JdbcAccountDao", you have to change the code that uses the AccountDao?

    Like I said, I see several potential problems, but I really cannot find nearly enough information to have a view of the whole picture concerning EJB 3.0.

    Guillaume
  15. From what I understand, the container intercept when new is done on an object and then inject the dependencies. (Using bytecode instrumentation I assume) Cedric/Gavin, is that right?
    No, one of the things that is specifically excluded is alterations to existing bytecode.

    Rather than a factory, it would be possible to use the EntityManager to set up the dependencies, something like:

    Account acct = new Account();
    em.injectDependencies(acct);
    // ... do stuff

    but, to me, that doesn't really seem to be simplifying things.

    Is a factory that bitter a pill to swallow?
  16. From what I understand, the container intercept when new is done on an object and then inject the dependencies. (Using bytecode instrumentation I assume) Cedric/Gavin, is that right?
    No, one of the things that is specifically excluded is alterations to existing bytecode.Rather than a factory, it would be possible to use the EntityManager to set up the dependencies, something like:Account acct = new Account();em.injectDependencies(acct);// ... do stuffbut, to me, that doesn't really seem to be simplifying things.Is a factory that bitter a pill to swallow?
    Agreed: you can't have your cake and eat it too.

    Either you use the POJO constructor and you need to have a way to trigger the injections (ugly IMO), or you use a factory.

    Also, note that POJO's you get from a query are automatically injected since they are instantiated and hydrated by the container, so I think overall, this use case ("want to use new *and* want the container to perform injection") will be pretty rare.

    Much ado for nothing (or in French, "a tornado in a glass of water").

    --
    Cedric
  17. Agreed: you can't have your cake and eat it too.Either you use the POJO constructor and you need to have a way to trigger the injections (ugly IMO), or you use a factory.Also, note that POJO's you get from a query are automatically injected since they are instantiated and hydrated by the container, so I think overall, this use case ("want to use new *and* want the container to perform injection") will be pretty rare.Much ado for nothing (or in French, "a tornado in a glass of water").-- Cedric
    I guess I missunderstood the few reports I read about EJB 3.0 then, I was under the impression that the container was assumed to modify the bytecode of the SessionBean class and and hook the dependency injecting in the constructor. I'm glad I had that part wrong, I didn't like it at all.

    However, if the container does not instrument the bytecode, I don't understand your arguments against constructor injection. Using your earlier example:
    Account a = new Account();
    a.setOwner("Cedric");
    EntityManager em = ... // get the EM
    em.save(a);
    em.flush();
    Assuming the Account would indeed care for a DataSource, how would container provided injection makes any of it easier? If it's a factory that create the instance and inject the DataSource, why should the code that uses the factory care how the DataSource was injected?
  18. I guess I missunderstood the few reports I read about EJB 3.0 then, I was under the impression that the container was assumed to modify the bytecode of the SessionBean class and and hook the dependency injecting in the constructor.
    The specification will certainly not place any requirement on implementation details, so don't worry about that. That being said, there are plenty of ways you can implement something like this, and personally, I would go with CGLib.
     I'm glad I had that part wrong, I didn't like it at all. However, if the container does not instrument the bytecode, I don't understand your arguments against constructor injection. Using your earlier example:
    Account a = new Account();a.setOwner("Cedric");EntityManager em = ... // get the EMem.save(a);em.flush();
    Assuming the Account would indeed care for a DataSource, how would container provided injection makes any of it easier? If it's a factory that create the instance and inject the DataSource, why should the code that uses the factory care how the DataSource was injected?
    I am afraid the DataSource example is what is causing all this confusion, so let's pick another example: your POJO will post a message on a JMS Topic which is defined externally.

    In the above example, unless the methods invoked on the POJO make use of this Topic, (setOwner()), injection won't be necessary. save() and flush() will succeed because the EntityManager has all the datasources and schema information it needs to perform these calls.

    Now, if you are going to invoke some business logic on your POJO that needs the Topic, you will have to either trigger the injection manually or look up the Topic yourself and create your POJO with it (remember that I said earlier that I was not opposed to your POJO having a constructor that takes this Topic, I was just arguing that it shouldn't be the preferred way to do this in a container).

    If you want to save yourself the trouble of parsing the XML file or whatever external way you used, you could imagine something like this:

    EntityManager em = ...;
    Topic topic = (Topic) em.lookup("jms/MyTopic");
    Account a = new Account(topic);

    A more implicit way is to have a "createInjection()" method on EntityManager.

    Once again, keep in mind that all these ideas are tentative. We are still discussing them on the EJB3 mailing-list and the API for EntityManager is far from being defined, so feel free to make suggestions.

    --
    Cedric
  19. In the above example, unless the methods invoked on the POJO make use of this Topic, (setOwner()), injection won't be necessary.
    Of course, you don't know which methods do need the Topic injected without knowledge of the implementation. This is a bad breakdown in encapsulation.

    We can use constructor injection, as per your example, but this is placing the responsibility on the application to perform the injection. It means the client code needs to know how to resolve all the dependencies for the object being constructed - in your example, the client needs to know that the Account object is dependent specifically on "jms/MyTopic" rather than some other one.

    On the other hand, with factory creation the container would be responsible for injecting the correct Topic into its new Account instance, either through its constructor or through a setter. I believe this leads to a simpler and more maintainable application.

    As you say, we are still discussing this on the EG list, but somehow I think some of the laundry will still get aired in public :)
  20. I was just arguing that it shouldn't be the preferred way to do this in a container).If you want to save yourself the trouble of parsing the XML file or whatever external way you used, you could imagine something like this:EntityManager em = ...;Topic topic = (Topic) em.lookup("jms/MyTopic");Account a = new Account(topic);A more implicit way is to have a "createInjection()" method on EntityManager.Once again, keep in mind that all these ideas are tentative. We are still discussing them on the EJB3 mailing-list and the API for EntityManager is far from being defined, so feel free to make suggestions.-- CedricI think that the major problem with this approch is that it is confusing domain objects (like Account) with services.

    Good design imo requires that for services interfaces should be used.

    Account a = new Account(topic)

    will work only if Account is concrete class.

    But if you have more then one implementation of Account and Account is an interface it won't even compile.

    But really this is not a probalem as simply not every class needs to be a component.
    If domain object needs to use some services it can obtain them as method parameters.

    Account a = new Account()

    a.someBusinessMethod( topic ) ;

    seems to be reasonable for me.


    Note that for EJB this code will be probably invoked inside some service(bean)
    and this bean will have its dependecy including "Topic" injected or they will be sometimes accesible via lookup.


    If you really want to use Account as a component (imo an overkill) factory/lookup methods are the only way to go as components should be only instantiated by container.

    Account a = lookup( Account.class )

    Note also that lookup methods should work with more complex data structures then single bean and one should be able to lookup List, Maps of components which have given role in the system. There is a few ways of doing it. The best know is probably via Selector(s) like it takes place in Avalon. More advanced could be driven by metadata or/and even query langauge.

    It should be possible to do things like:
    Command command = lookup( Command.class, "add user");

     or
    List<Command> commands = lookupList( Command.class );
    Command command = CommandListHelper.get( commaands, "add user");

     or

    Map<Command, String> commandMap = lookupMap( Command.class );
    Command command = commandMap.get( "add user" ) ;


    But the code like

    Command command = new AddUserCommand();

    seems to be against the concept of loose coupling and the dependnecy injection is not well (if at all) covered.


    Michal
  21. Account acct = new Account();
    em.injectDependencies(acct);
    NO! The EJB should not work this way!!!!! When I get the object I should allready be with all declarative things. Otherwise it will be:

    transactionManager.injectTransaction(acct);
    securityManager.injectPermissions(acct);

    NO! We work inside container, container should do staff.

    How properly instrumenting bytecode - that's a question.
  22. I think these are very interesting concerns, Guillaume.

    I especially would like to see the issue of multiple configurations addressed.

    Will one be able to work without the annotations in EJB 3? In this case, could one do without the annotations and just specify things in the deployment descriptor? It seems overly complex (having the description in two places), but it might solve the issue with multiple configurations, and having a component depend on EJB container stuff at runtime.

    --Kevin
  23. So why not just require a factory?Account a = (Account) em.new(Account.class);a.setName("cedric");em.save(a);em.flush();
    Just a thought. If it's a dependency, doesn't that mean that the object needs that dependency in it's life, meaning right after construction ? Couldn't we just annotate the setFoo method with @Injector or @DependencyInjector (personally I don't agree with @Inject) or @ContainerProvided and the container calls it with right after object creation (after constructor is called?)? Or for cases that you would need that dependency right in the constructor (where do I know ?) the container could intercept (see @AOP :-)) the constructor and inject the dependency before any other client provided in constructor initialization/statements occur ? I don't know. I'm just expressing an oppinion.
  24. I really liked the @ContainerProvided name. Hide the buzzword, show the general idea. But damn, can't we stop fighting over the name of the annotation name, and focus on why it's needed, after all? :)

    Personally, I agree with Aslak here, in that constructor-based dependency injection is a simpler approach, and encourages simpler code (less contractual burden on the POJO interface, at least). If there's no reason for an object to exist without its dependencies, then why create it?

    Another issue that I haven't seen brought up in this thread yet, these annotations force your code to rely on the J2EE runtime - you're importing javax.ejb.something.Inject, or whatever the name of the annotation class is. Even if it's a very small JAR, it's still something undesirable if you want your components to be used in a different context (say, a bare Servlet container, a Swing app, an Applet). Pico, Spring and, in a way or another, Avalon components can be used with absolutely no runtime dependencies on the container. Why mustn't the new EJBs?

    One possible solution that comes to mind would be adopting a "fine, you don't want annotations, you can use a deployment descriptor instead". If you want XML, then use it, if you want the annotations, then use them, but if you don't want neither, there's an API there waiting for you. Build the API first, then get fancy with annotations, XML, Groovy or whatever is the assembly and configuration format du jour.
  25. I really liked the @ContainerProvided name. Hide the buzzword, show the general idea. But damn, can't we stop fighting over the name of the annotation name, and focus on why it's needed, after all? :)Personally, I agree with Aslak here, in that constructor-based dependency injection is a simpler approach, and encourages simpler code (less contractual burden on the POJO interface, at least). If there's no reason for an object to exist without its dependencies, then why create it?
    Why do you care how dependencies are injected?
    You will just ask container for instance of given component and you don't care.
    If component initialization happens only in construcoter or it is constructor/setters combo or even constructor/setters + callback method it simply does not matter as this is hidden from you by container.
    Another issue that I haven't seen brought up in this thread yet, these annotations force your code to rely on the J2EE runtime - you're importing javax.ejb.something.Inject, or whatever the name of the annotation class is. Even if it's a very small JAR, it's still something undesirable if you want your components to be used in a different context (say, a bare Servlet container, a Swing app, an Applet). Pico, Spring and, in a way or another, Avalon components can be used with absolutely no runtime dependencies on the container. Why mustn't the new EJBs?
    This is not fully true. Avalon components needs avalon-api and avalon runtime to work. You can also ask how many of Picco, Spring users would like to use their application without container. I suppose almost none of them. Once you are used to container and component oriented way of thinking you really don't want to have an applications which can be run without any container. And components by its definition (Componet is self-contained piece of software that can be independently deployed and plugged into an environment that provides a compatible socket.) needs to have container which is sometimes even called Component Virtual Machine. If you are addicted picco user you will use in in servlets, applets and pretty much everywhere. It certainly does not mean that all containers are the same. There is hugh diffeence between for example picco or EJB container (for EJB 2.x). The idea of having invisible container is quite appealing and I like it but in reality you will still need a conatiner to run components and your components = POJO will be written with container in their minds and probably often using some container provided services like injection of dependencies and configuration settings.


    [...]

    Michal
  26. Why do you care how dependencies are injected? You will just ask container for instance of given component and you don't care.If component initialization happens only in construcoter or it is constructor/setters combo or even constructor/setters + callback method it simply does not matter as this is hidden from you by container.
    I don't see how this is hidden from me by the container, as this is directly linked to the contracts my components have to obey so the container knows how to handle them. Am I missing something?
    You can also ask how many of Pico, Spring users would like to use their application without container.
    Three words: unit test cases. But then, what I'm arguing about here is that components should ideally not have any dependencies on the container, but directly on the services themselves, if there's need for them (for instance, you would depend on a DataSource, or a TimerService, TransactionService, whatever), but you shouldn't glue your component to the J2EE API just because you have to stick some metadata in it.
  27. Why do you care how dependencies are injected? You will just ask container for instance of given component and you don't care.If component initialization happens only in construcoter or it is constructor/setters combo or even constructor/setters + callback method it simply does not matter as this is hidden from you by container.
    I don't see how this is hidden from me by the container, as this is directly linked to the contracts my components have to obey so the container knows how to handle them. Am I missing something?
    I mean that conatiner completly hides the details how given component is instantiated from the point of view of the user of this component

    If you do:

    Foo foo = lookup( Foo.class)

    you don't care what's going on behind the scene


    if it is

    Foo foo = new FooImpl( lookup( Baa.class), lookup( Baa.class) )

    or

    Foo foo = new FooImpl( )
    foo.setBaa1( lookup( Baa.class) )

    or

    Foo foo = new FooImpl( )
    assignToPrivateField( foo,lookup( Baa.class), "bas" );


    Certainly when you are the author of the component you need to choose your strategy and make it known to the container. That's why I wrote that when
    you are writing a componet you are writing it accordingly to certain contract which must be supported by container. Any conatiner can support dozen of different contracts. Some containers are supporting only one contract and there
    is no need to inform the container what's your contract using metadata, but still you might need to use meta data for insturcting container how it should aplay given contract.

    So it is like you are saying:
    Component A -- use constructor injection for this component
    Component B -- use setter injection + use this meta data
                    which lists wich should be injeted



    So as the author you do care hwo things work but as the user you don't.
    You can also ask how many of Pico, Spring users would like to use their application without container.
    Three words: unit test cases. But then, what I'm arguing about here is that components should ideally not have any dependencies on the container, but directly on the services themselves, if there's need for them (for instance, you would depend on a DataSource, or a TimerService, TransactionService, whatever), but you shouldn't glue your component to the J2EE API just because you have to stick some metadata in it.
    This sounds nice but is too simple to make it usable for anything more complex simply becouse in pratice components often must have well defined lifecycle.
    For example they can be started/stopped/passivated/actiavted and so on.

    Even pico components implement interfaces like Startable or Disposable and you have to distribute them with jar which defines those interfcases. For me the container really simplifies things becouse it controls the lifecycle of your component. Without it the code is simply much harder.

    You don't wan't t do:

    Foo foo = new Foo();
    foo.initialize();
    foo.start();

    ....
    foo.dispose();
    foo.stop();


    you just wan't to do:

    Foo foo = lookup( Foo.class);
    release( foo );

    and you can igore the life cycle of the component container will take care of that. You don't need to know if this component implements Startable, Disposable or both. Or maybe dozen other callback methods.
    That's why I want to use containers - they make my life simpler. If your component can exists without callback methods - it is fine - but not all components do.

    I didn't also understod your remark regarding unit tests. Have you seen how they
    are implemented for componets written for "light-weight" containers or
    even for open-ejb? You are still using container for unit tests. It's nothig really scary or more difficult to write then ordinary test cases. Sometimes they are even much simpler.

    Michal
  28. IMHO, the components should be container agnostic, so if I ever have to take a POJO component deployed on Spring and deploy it on Pico, the only thing I will have to change are the descritor files. With this annotation schema in EJB3.0, will I be able to do it, like take a EJB3 component and redeploy it on Spring or Pico without a single change in POJO's code?

    Else we can change the meaning of POJO: Polluted Old Java Object... ;)

    Now, if annotations were standardized between all containers, it should work. Better yet if component's source code were container agnostic, and descriptor files were standardized, at least for the basic services (DI, IoC): this way I would be able to easily redeploy to whichever LWFW _or_ EJB3 container with very little work.

    People won't be happy if one of the goals of these annotations end up being to tie your component to EJB3 specification.

    Regards,
    Henrique Steckelberg
  29. Maybe I am running in a smart container that will instantiate them lazily, only when they are used for the first time.
    To me this is indicative of a problem with ejb and j2ee specs: there is too much involvement by container vendors, who are concerned with getting container requirements looked after (I used to work in a CORBA company and it was the same problem at OMG meetings), resulting in big design up front and unhappy compromises.

    Pico, Spring and other lightweight containers "grew" from real usage patterns of people writing business software, and these people care little about the container. The "needs" of the container are totally subjugated relative to the needs to the container user.

    @Inject really seems to me to be a container aid. In fact they must be, because I can already do injection without it using Pico and Spring. I think EJB 3.0 is in danger of giving up to much to container vendors and having another mess that makes nobody really happy.
  30. In other words, materializing the datasource is a crosscutting concern, it should not be part of my business logic
    You are right! Having the constructor declare the dependency will break you object contract, if you decide to change your implementation and replace the dependency with another one. And that is why I liked the comment in Adrian blogs that the annotation should go on the private field instead of a method. In fact there should be no method to set the injected property.

    If you have the @ContainerProvided (I really like this annotation name as it really describes it's meaning) annotation on the field, then it is the respossibility of the container to provide it when the field is accessed. It really allows for lazy injection as it can be done in a Aspect Oriented fashion (field access pointcut). The method based injection will not really allow the container to do true lazy injection as it will have to do it when any method on the object will be called, even if that method makes no use of the injected dependency. On the other hand, if the injection is made when the field describing the dependency is accessed, the container can wait until that point to inject it.
  31. The method based injection will not really allow the container to do true lazy injection as it will have to do it when any method on the object will be called, even if that method makes no use of the injected dependency. On the other hand, if the injection is made when the field describing the dependency is accessed, the container can wait until that point to inject it.
    This not not really true. You can easly have "lazy injection" in no matter which way you will inject your depedencies and AOP is not really needed for that and is not much helpfull here. Simply you container should inject connectors and not componets.

    In fact there is much more reason why connectors should be used anyway. Some of there are briefly mentioned here:

    http://nenya.ms.mff.cuni.cz/projects/sofa/tools/doc/compmodel.html#connectorDesign


    Michal
  32. Injection should have no impact on my business logic nor on my public or private API. With your suggestion, it will infect all my objects, which is exactly what we are trying to avoid.
    Of course it should have an impact. Injection points (constructors or setters) define the component's contact. It is analogous to preconditions. Basically it means:


    I refuse to operate correctly if one of my dependencies cannot be satisfied.


    If you are saying that injection should have no impact, it means to me that the component should work fine whether certain objects are injected or not. In which case we're no longer talking about true dependencies.

    Dependencies aren't optional.

    An "optional dependency" as you describe it is not a true dependency. From what you are saying it sounds like the EJB3 @Inject directive is for optional dependencies. This doesn't look good at all.
  33. It is redundant, as the well-established Java Bean model for properties is enough.
    It is enough but it pollutes your Java type system, so annotations are a better way. Same for marker interfaces.
    I don't understand this point--a setter method without an annotation "pollutes your Java type system", but a setter method with an annotation does not? What am I missing?
    This smells of design up-front to me. I have never heard of anyone wanting this kind of separation.
    JNDI names, datasources, JMS topics and queues... the examples are endless.
    Hmm, isn't dependency injection supposed to be an alternative to JNDI--i.e., the container injects the dependencies instead of the component explicitly looking them up using JNDI? Injecting JNDI names would seem to be missing the point.
    What's declared in the constructor(s) is what the container has to provide. Period. And you can still have setters on the same class that would be ignored by the container.Aslak
    Are you suggesting I should add a constructor to my POJO that takes a datasource? A connection pool?Now that's what I call intrusive.
    I don't see that. Either way, the component is dependent on the datasource--constructor injection just makes that dependency more explicit, which I'd regard as a good thing.

    I guess what bothers me is this: to me, the whole point of DI is about minimizing the dependencies of a component on it's container--so, components designed using DI could run inside or outside of an EJB container, or perhaps even in a J2ME environment. But all this stuff about @Inject annotations seems to serve no purpose except to make the components dependent on the J2EE environment. While I can understand why writers of EJB containers might not see that as a bad thing, it does seem to be missing the point of DI quite badly.

    Best regards,
    Robert Lowe
    http://rmlowe.com/
  34. I don't understand this point--a setter method without an annotation "pollutes your Java type system", but a setter method with an annotation does not? What am I missing?
    I should have been clearer. An annotation doesn't pollute your type system in the sense that it doesn't impact the API of your object. In other words, it will not appear in a "javap" of your class, nor if you use code completion in your IDE.
    Hmm, isn't dependency injection supposed to be an alternative to JNDI--i.e., the container injects the dependencies instead of the component explicitly looking them up using JNDI? Injecting JNDI names would seem to be missing the point.
    Right, that's one way of looking at it. Once again, the important part is that since this information is provided by the container, you, as the author of the business logic or of the unit test, should not have to be aware of it.
    I guess what bothers me is this: to me, the whole point of DI is about minimizing the dependencies of a component on it's container
    I don't see it this way. Like Aslak said, the dependency on a DataSource is a reality: the object needs it to function. What dependency injection brings to the picture is a clear separation between business logic (which you provide) and deployment logic (which the container provides).

    --
    Cedric
    http://beust.com/weblog
  35. Are you suggesting I should add a constructor to my POJO that takes a datasource? A connection pool? Now that's what I call intrusive. Injection should have no impact on my business logic nor on my public or private API.
    Cedric,

    How is that intrusive? The datasource is a required dependency, without it the client bean (presumably a DAO) would be in an unworkable, invalid state. This makes the datasource a fine candidate for constructor injection IMO (since as we all know, constructors allow us to enforce the creation of well-formed objects and establish and protect a class's invariants.)

    Furthermore, to me this example exhibits a natural dependency between collaborators; that is, it just "feels" natural that a DAO depend on a data source. And it is obvious that dependency is mandatory. I see no polluting going on here.

    A simple constructor ensures an object is instantiated and initialized in full inside *or* outside a container (I _much_ prefer the term 'assembler' here.) I mean, who gives a flying flip who instantiates it, the object itself should just be a properly formed, plain-old OO OBJECT so it can be used by any number of assemblers (human or container alike ;-)))

    What if I wanted to instantiate this DAO programatically within a client side environment, like a swing/swt app? I'd much prefer the contract of a constructor to prevent my junior developers from introducing subtle "I forgot to invoke <x> setter method" bugs. I'd much prefer one of the more sophisticated IoC containers that supports constructor-based injection and allows fine grained assembling of my objects and their dependencies (which ensures I don't go around "polluting" my objects with too many responsibilities.)

    IMO it's all about sound OO design principles. I don't want to sacrafice those principles for any implementation technology, EJB 3.0 included. I don't see the need for an @Inject metadata tag, because assembling (wiring) IMO should happen externally (it's a separation of concerns--I would prefer to have assembling logic and configuration in one centralized place so I can easily see the big picture of how my objects are being configured! And to further decouple configuration from use!) Assembling should be possible in many ways in _different_ deployment environments, for example by-hand by me or my collegue, or automatically by some whiz-bang super-magic IoC container (running within a EJB environment or standalone.)
  36. What if I wanted to instantiate this DAO programatically within a client side environment, like a swing/swt app?
    Note that I am not opposed to the idea of providing a constructor that takes a DataSource, I am just arguing that it should not be the only constructor available and that when you are running your object in the container (or assembler, as you call it, which is a good name as well), you shouldn't be using this constructor because this information will be injected for you.

    For example, if you are writing a unit test, you implement your own factory of objects that initializes the object properly (either by looking up the @ContainerProvided annotation, or by constructor dependency or by setter dependency) so that your unit test can focus on testing it, instead of polluting i
    What if I wanted to instantiate this DAO programatically within a client side environment, like a swing/swt app?
    Note that I am not opposed to the idea of providing a constructor that takes a DataSource, I am just arguing that it should not be the only constructor available and that when you are running your object in the container (or assembler, as you call it, which is a good name as well), you shouldn't be using this constructor because this information will be injected for you.

    For example, if you are writing a unit test, you implement your own factory of objects that initializes the object properly (either by looking up the @ContainerProvided annotation, or by constructor dependency or by setter dependency) so that your unit test can focus on testing it, instead of polluting it with non business logic.
    I don't see the need for an @Inject metadata tag, because assembling (wiring) IMO should happen externally (it's a separation of concerns--I would prefer to have assembling logic and configuration in one centralized place so I can easily see the big picture of how my objects are being configured!
    It seems to me you are precisely arguing for what I am trying to achieve :-)

    If the only way to set the datasource is in your constructor, you are mixing up assembling logic and business logic. The one centralized place to have your assembling and configuration logic is in the container, not scattered in your POJO constructors...

    --
    Cedric
    t with non business logic.
    I don't see the need for an @Inject metadata tag, because assembling (wiring) IMO should happen externally (it's a separation of concerns--I would prefer to have assembling logic and configuration in one centralized place so I can easily see the big picture of how my objects are being configured!
    --
    Cedric
  37. Oops[ Go to top ]

    Sorry, messed up copy/paste in my previous message, trying again
    What if I wanted to instantiate this DAO programatically within a client side environment, like a swing/swt app?
    Note that I am not opposed to the idea of providing a constructor that takes a DataSource, I am just arguing that it should not be the only constructor available and that when you are running your object in the container (or assembler, as you call it, which is a good name as well), you shouldn't be using this constructor because this information will be injected for you.

    For example, if you are writing a unit test, you implement your own factory of objects that initializes the object properly (either by looking up the @ContainerProvided annotation, or by constructor dependency or by setter dependency) so that your unit test can focus on testing it, instead of polluting it with non business logic.
    I don't see the need for an @Inject metadata tag, because assembling (wiring) IMO should happen externally (it's a separation of concerns--I would prefer to have assembling logic and configuration in one centralized place so I can easily see the big picture of how my objects are being configured!
    It seems to me you are precisely arguing for what I am trying to achieve :-)

    If the only way to set the datasource is in your constructor, you are mixing up assembling logic and business logic. The one centralized place to have your assembling and configuration logic is in the container, not scattered in your POJO constructors...

    --
    Cedric
  38. Oops[ Go to top ]

    It seems to me you are precisely arguing for what I am trying to achieve :-)
    :-) Yes I think so! But annotations to me aren't necessarily the answer. Think about this: when I look at a centralized assembler configuration source, like for example a configuration file, I can see how numerous objects are "wired" together and get a feel for how everything fits. I can stub out the definition of one implementation of a service and replace it with another, and immediately see what clients are effected. I get a "big picture" view of my dependencies! It seems with annotations you've got a tree's view of a single component - not a big picture view. Continuing the analogy, you've got more trees to hack to vary the assembly and configuration of your application.
    If the only way to set the datasource is in your constructor, you are mixing up assembling logic and business logic. The one centralized place to have your assembling and configuration logic is in the container, not scattered in your POJO constructors...
    I disagree here. You've got the dependency regardless. Doesn't matter how it gets injected, you're still importing javax.sql.DataSource, and you still need a non-null DataSource instance to work (so you've already muddied the water so to speak.) If you find yourself mixing a DataSource with complex business logic, perhaps it's time to refactor: put that DS behind a DAO and inject the DAO, further decoupling business logic from persistent logic.

    Keith
    http://www.jroller.com/page/kdonald
  39. Moreover, if the EJB3 spec goes for constructor injection , there would be no need for annotations whatsoever. What's declared in the constructor(s) is what the container has to provide. Period.
    I agree that constructor injection is a winner. For me the compelling motivation is a simpler bean lifecycle. Settor injection's bean state model is more complex. It has an extra state where the bean is instantiated but uninitialized, and the contract must include a contrived stimulus to subsequently signal that the bean is finally ready for use. With settor injection the bean's constructor is forbidden to access dependencies. This violates the spirit of POJO, and potentially contorts a bean's implementation.

    What folks are forgetting is that the bias towards settor injection is for historic reasons. It has to do with maintaining a pool of reusable beans, which can't be done with ctor injection. But Sun has since denounced object pooling, so the historic bias is no longer relevant. It's just lame baggage, or as Sun's HotSpot Performance FAQ says:

    "Pooling objects will cause them to live longer than necessary. The garbage collection methods will be much more efficient if you let it do the memory management. We strongly advise taking out object pools."
  40. It's just lame baggage, or as Sun's HotSpot Performance FAQ says:"Pooling objects will cause them to live longer than necessary. The garbage collection methods will be much more efficient if you let it do the memory management. We strongly advise taking out object pools."
    This FAQ totally misses the point. The interest in pooling is not in avoiding garbage collection but in avoiding creating objects whose constructor is very expensive.

    Memory is cheap and expansible, time is not (*). Between a constructor that will take 1/10s to complete and getting an object from a pool, which is quasi-instantaneous, I'll take pooling any time of the day.

    --
    Cedric
    (*) Well, this is not quite true, I will concede that pooling is less interesting when you are traveling at the speed of light, but let's not nitpick.
  41. The interest in pooling is not in avoiding garbage collection but in avoiding creating objects whose constructor is very expensive.
    I agree that reclamation is cheap, since a multiprocessor can do it asynchronously on an otherwise idle CPU.

    I disagree that empty bean construction (without injection) is slow. Can you cite evidence or otherwise briefly explain why empty bean construction is usually slow within a container?
  42. The interest in pooling is not in avoiding garbage collection but in avoiding creating objects whose constructor is very expensive.
    I agree that reclamation is cheap, since a multiprocessor can do it asynchronously on an otherwise idle CPU.I disagree that empty bean construction (without injection) is slow. Can you cite evidence or otherwise briefly explain why empty bean construction is usually slow within a container?
    I never said "empty bean construction". On the contrary, I said "expensive constructors". Whenever an object is expensive to create, you are probably better off pooling it.

    --
    Cedric
  43. <Whenever an object is expensive to create, you are probably better off pooling it.-- Cedric
    The point is: Typical business objects do not hold non-thread-safe resources. They access a JDBC DataSource or Hibernate SessionFactory, which are perfectly thread-safe: Just Connections respectively Sessions aren't, but those are not kept in instance variables - rather just used within method scope.

    So why pool Stateless Session Beans then? As long as all the state of an object is thread-safe, there is no point in pooling it and locking it during method invocations. Note that pooling has conceptual disadvantages, like multiple copies of configurations or caches that are held in instance variables.

    Juergen
  44. I never said "empty bean construction". On the contrary, I said "expensive constructors".
    You defended settor injection and the pooling of blank beans. You complained that construction is slow. So we're talking about the construction of blank beans -- those that haven't recieved dependencies. I still don't understand why you consider the construction of blank beans to be slow. HotSpot creates millions of objects per second.
  45. I never said "empty bean construction". On the contrary, I said "expensive constructors".
    You defended settor injection and the pooling of blank beans. You complained that construction is slow. So we're talking about the construction of blank beans -- those that haven't recieved dependencies. I still don't understand why you consider the construction of blank beans to be slow. HotSpot creates millions of objects per second.
    Just because a bean hasn't received any injection doesn't mean it's "blank". Its constructor can still have several parameters and be expensive (e.g. parsing an XML file).

    And please, don't misquote me, I never used the term "blank bean", much less said "constructing blank beans is expensive".

    --
    Cedric
  46. Moreover, if the EJB3 spec goes for constructor injection , there would be no need for annotations whatsoever. What's declared in the constructor(s) is what the container has to provide. Period.
    I agree that constructor injection is a winner. For me the compelling motivation is a simpler bean lifecycle. Settor injection's bean state model is more complex. It has an extra state where the bean is instantiated but uninitialized, and the contract must include a contrived stimulus to subsequently signal that the bean is finally ready for use. With settor injection the bean's constructor is forbidden to access dependencies.
    Bean will be accesible only when container lookup method will return it to you. No sooner. And normaly it will after
    a) instantiation
    b) dependency injection
    c) configuration setting injection
    d) initialization (execution of callback methods which are defined by lifecycle like initialize() , start() etc)

    I think that constructor dependecy injection is fine for injecting small number of dependencies. But is not that nice when the number of dependencies grows and imo is not at all applicable for injecting configuration settings (imagine that your component is database connection pool and has 20 or more parameters). There are some patterns used as workaround for that. But they are quite ugly and more artificial then field injection or setter injection.
    Again why there should ba winner? Why many solution cannot be supported so you
    have choice if you like field injection, setter injection or constructor injection?
      This violates the spirit of POJO, and potentially contorts a bean's implementation.What folks are forgetting is that the bias towards settor injection is for historic reasons. It has to do with maintaining a pool of reusable beans, which can't be done with ctor injection. But Sun has since denounced object pooling, so the historic bias is no longer relevant.
    I think that setter injection has completly different historical motivation.
    It was used for Java Beans Components which were supposed to be used for GUIs.
    This model allows you even to distinguish modeling phase and runtime phase. It means that you could take existing instance of Java Bean - switch it to modeling stage and set any of its properties to a different value.
    For example if your bean contains configuration settings for database connection pool you are able to change a value of "poolSize". Component model defined by Java Beans has a lot of nice features which are not well known (like hierarchical contexts, context lookup operations etc) and I think many things from this model will be borrowed for managment acpects of of server side components (jmx is not a solution here)

    Michal
  47. Posted my thoughts here, but the gist is this:

    @Inject is not enough, as it's been shown. It needs a way to be able to dereference a specific instance of a dependent type. Spring's XML provides this. It could also be provided by supplying parameters to the annotation. I'm still not sold on tying my components to EJB 3 when I could just use a completely non-invasive framework like Spring, however. Why limit my options?
  48. Why adjectives?[ Go to top ]

    Sorry, I actually can't see any particular reason why metadata is always adjectival. For example, I see no reason on earth why the following would not be a perfectly sensible javadoc comment:


     /**
      * Call this method immediately after
      * instantiating the object
      */
     public void setFoo(Foo foo) { ... }

    Since JavaDoc is indisputably metadata, what's wrong with an annotation which says the same thing?

    Lets translate @ContainerProvided setFoo() into English:

      "this setter method is provided with the container"

    wtf? Does that make any sense at all??

    How about @Inject setFoo():

      "inject a dependency using this setter method"

    I know which one I prefer.
  49. Why adjectives?[ Go to top ]

    Sorry, I actually can't see any particular reason why metadata is always adjectival. For example, I see no reason on earth why the following would not be a perfectly sensible javadoc comment: /** * Call this method immediately after * instantiating the object */ public void setFoo(Foo foo) { ... }Since JavaDoc is indisputably metadata, what's wrong with an annotation which says the same thing?Lets translate @ContainerProvided setFoo() into English: "this setter method is provided with the container"wtf? Does that make any sense at all??How about @Inject setFoo(): "inject a dependency using this setter method"I know which one I prefer.
    How about @InvokedByContainer?

    --
    Cedric
  50. Why adjectives?[ Go to top ]

    How about @InvokedByContainer?
    Like equals() ?

    I prefer Jason Carreira's suggestion of @Dependency
  51. @WhatToCallTheBloodyThing[ Go to top ]

    How about:

    @Injector

    Or:

    @DependencyInjector
  52. Why adjectives?[ Go to top ]

    When you think about it, a javadoc block really is a "description" metadata attribute of an element:

    @description
       Call this method immediately after instantiating the object (long desc)
    public void setFoo(Foo) { ... }

    This nicely illustrates how I think metadata is intended to be used. These tags are attributes; data about another element. @Inject is not data about data, it's a verb.

    Adrian has a valid point. A boolean attribute makes more sense here, and I believe is more consistent with how the metadata facility should be used in general.
  53. Why adjectives?[ Go to top ]

    I do not need magic from container too, if container lets me configure components myself then I can use any framework to do it and to reuse my components. Anotations is a good new feature, but I do not think we need to use it for evrything. It it must be mre interesting to talk about monitoring,clustering, load balancing, security (and more serius things than design patterns).
    I have a few faworite design patterns too. I will be happy if container will let me implement it my design pattern, but I do not need any help from container to implement my faworite design pattern,
  54. Why adjectives?[ Go to top ]

    Lets translate @ContainerProvided setFoo() into English: "this setter method is provided with the container"
    And hence the suggestion to provide the annotation on the property instead of the setter, I think:

    @ContainerProvided
    FooType foo;

    Now this can be read: "foo is provided by the container". This actually makes more sense to me.

    If the annotation has to be on the setter, Cedric's version @InvokedByContainer is fine too.
  55. Why adjectives?[ Go to top ]

    Lets translate @ContainerProvided setFoo() into English: "this setter method is provided with the container"
    And hence the suggestion to provide the annotation on the property instead of the setter, I think:@ContainerProvidedFooType foo;Now this can be read: "foo is provided by the container". This actually makes more sense to me.If the annotation has to be on the setter, Cedric's version @InvokedByContainer is fine too.
    The annotation absolutely should /not/ be on the instvar. A dependency need not be implemented as an instance variable. There is no requirement that every setter method must have a corresponding instance variable with the same name. (I can think of use cases where the injected object is used only in the injector method.)

    I am happy with @Injector, which reads:

    "this setter method is a dependency injector method"
  56. @Required or @Mandatory[ Go to top ]

    How about a simple @Required or @Mandatory.
    One could also do the reverse and assume all setFoo()s are mandatory, and have an @Optional to mark those that aren't.

    Many of the other suggestions make it should more complicated than it is, from the beans point of view. All the bean cares about is that the property "foo" is not optional, hence someone must call setFoo(). How it gets done (dependency injection, etc..) is an implementation detail that shouldn't concern the bean.

    It seems like @Required/@Mandatory and @Optional would be good additions to the JavaBean spec in general (not just EJB).

    -Yonik
  57. Why adjectives?[ Go to top ]

    The annotation absolutely should /not/ be on the instvar. A dependency need not be implemented as an instance variable. There is no requirement that every setter method must have a corresponding instance variable with the same name. (I can think of use cases where the injected object is used only in the injector method.)I am happy with @Injector, which reads:"this setter method is a dependency injector method"Actually I do like @Injector and your arguments are convincing, so I succumb :)
  58. Why adjectives?[ Go to top ]

    How about @Inject setFoo():  "inject a dependency using this setter method"I know which one I prefer.
    Gavin, thanks for some level headed comment, the thread is very confusing to me. But as I make my mind I think I prefer @inject annotations. Is this a real technical discussion or is it "much ado about nothing" as cedric beust claims?

    Dependencies defined by type with a verb that says "inject" is a clear and explicit command I am comfortable issuing to the container. I like it. EJB3 is a container spec and talking to a container definitely simplifies the programming model without making assumptions like "constructor injector only".

    Containers are a dime a dozen today so I am not losing sleep over the "POJO testability" of the programs. I don't think I want to pay for heavy XML to have that fringe benefit. Give me an EJB3 container that simplifies my life, thank you.
  59. Hm, I am quite puzzled at what I gain with this injection mechanism. Suppose I have an EJB - say it posts to a queue or whatever, doesn't really matter - and I want to deploy the EJB twice to the same container using different queues.

    The injection annotation will state that I inject a queue of some name at that point - it would be naive to assume that there is just one JMS server let alone one queue in each J2EE environment.

    So the annotation needs to be resolved somewhere. Chances are in the deployment descriptor or in the server itself. But either way will need an additional configuration step after all.

    I do fail to see this is any better than just mapping a couple of getter methods from the bean instance. The actual resolving cannot be done in the annotation after all.
  60. I see annotations a bit differently. I see them as a way to plug in typed syntax into the Java language. Although the intent of JSR-175 may have been to only provide adjectives and adverbs, there is absolutely no reason that you shouldn't use it to introduce verbs. This kind of talk is like the annoying student who only raises his hand to correct the teacher for spelling mistakes.

    The @inject is a hint to the container (whatever container it may be) to inject a certain dependency. There is absolutely no reason the @inject tag could be removed and have all these depdencies defined in XML. I myself prefer the XML approach as it keeps my objects clean, but it seems the majority of programmers, at least those using XDoclet, do not prefer XML but rather to make things obvious in the Bean class.

    Constructor dependency injection is not possible in EJB land because of the pooling requirements of the specification.

    The field vs. setter debate is also a silly argument as well as I do not think there is a "correct" way. They are all correct. What I like about field injection is that with an AOP framework you can throw a runtime exception on a field write of an injected dependency to enforce semantics. Field injection also makes a lot of sense outside of EJB land for context/thread based dependencies as well where setters just couldn't handle multi threaded invocations and thread based dependencies. I'll write a blog on this eventually.

    The downside with field injection is testability. BUT...this isn't a problem if your IoC is driven by AOP. Especially true with JBoss AOP as aspects are bound at deploy time. IoC containers relying on traditional OOP would have a problem though of course.

    Bill