Annotation-Driven Dependency Injection in Spring 2.1

Mark Fisher

Spring 2.0 introduced annotation support and annotation-aware configuration options that can be leveraged by Spring users who are developing with Java 5 (or later versions):

@Transactional for demarcating and configuring transaction definitions
@Aspect (AspectJ) for defining aspects along with @Pointcut definitions and advice (@Before, @After, @Around)
@Repository for indicating a class that is operating as a repository (a.k.a. Data Access Object or DAO)
@Required for enforcing annotated bean properties are provided a value

With Spring 2.1, this theme of annotation-driven configuration has been significantly extended and will continue to evolve as we progress toward the RC1 release. In fact, it is now possible to drive Spring's dependency injection via annotations. Furthermore, Spring can discover beans that need to be configured within an application context.

This blog entry will serve as a tutorial-style introduction to the basic features in 10 easy-to-follow steps. I will follow up later in the week with information on some more advanced features and customization options. If you are interested in alternative configuration options, you should also check out the Spring Java Configuration project and this blog.

This tutorial requires at least Java 5, and Java 6 is recommended (otherwise there is a single requirement at the end of step 1).

Step 1:

Grab spring-framework-2.1-m1-with-dependencies.zip. After extracting the archive, you will find the spring.jar and spring-mock.jar in the 'dist' directory. Add them to your CLASSPATH as well as the following (paths shown are relative to the 'lib' directory of the extracted 2.1-m1 archive):

  • asm/asm-2.2.3.jar
  • asm/asm-commons-2.2.3.jar
  • aspectj/aspectjweaver.jar
  • hsqldb/hsqldb.jar
  • jakarta-commons/commons-logging.jar
  • log4j/log4j-1.2.14.jar

(NOTE: If you are not running on Java 6, you will also need to add j2ee/common-annotations.jar)

Step 2:

Provide the interfaces and classes for the example. I have tried to keep it as simple as possible yet capable of demonstrating the main functionality. I am including all of the code and configuration in a single "blog" package. I would encourage following that same guideline so that the examples work as-is; otherwise, be sure to make the necessary modifications. First, the GreetingService interface:

public interface GreetingService {
    String greet(String name);
}

Then, a simple implementation:

public class GreetingServiceImpl implements GreetingService {
    private MessageRepository messageRepository;

    public void setMessageRepository(MessageRepository messageRepository) {
        this.messageRepository = messageRepository;
    }

    public String greet(String name) {
        Locale locale = Locale.getDefault();
        String message = messageRepository.getMessage(locale.getDisplayLanguage());
        return message + " " + name;
    }
}

Since the service depends upon a MessageRepository, define that interface next:

public interface MessageRepository {
    String getMessage(String language);
}

And for now, a stub implementation:

public class StubMessageRepository implements MessageRepository {
    Map<String,String> messages = new HashMap<String,String>();

    public void initialize() {
        messages.put("English", "Welcome");
        messages.put("Deutsch", "Willkommen");
    }

    public String getMessage(String language) {
        return messages.get(language);
    }
}

Step 3:

Define the beans for a Spring application context. Notice, that I am including a new 'context' namespace (NOTE: the 'aop' namespace is also included here and will be used in the final step):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.1.xsd"
>

     
    <bean class="blog.GreetingServiceImpl"/>

    <bean class="blog.StubMessageRepository"/>

</beans>

Obviously this configuration looks a little sparse. As you can probably guess, the 'context' namespace will soon play a role.

Step 4:

Provide a simple test case leveraging Spring's base support class:

public class GreetingServiceImplTests extends AbstractDependencyInjectionSpringContextTests {
    private GreetingService greetingService;

    public void setGreetingService(GreetingService greetingService) {
        this.greetingService = greetingService;
    }

    @Override
    protected String[] getConfigLocations() {
        return new String[] { "/blog/applicationContext.xml" };
    }

    public void testEnglishWelcome() {
        Locale.setDefault(Locale.ENGLISH);
        String name = "Spring Community";
        String greeting = greetingService.greet(name);
        assertEquals("Welcome " + name, greeting);
    }

    public void testGermanWelcome() {
        Locale.setDefault(Locale.GERMAN);
        String name = "Spring Community";
        String greeting = greetingService.greet(name);
        assertEquals("Willkommen " + name, greeting);
    }
}

Try running the tests and notice that they fail with a NullPointerException. This is to be expected since the GreetingServiceImpl has not been provided a MessageRepository. In the next two steps, you will add annotations to drive the dependency injection and initialization respectively.

Step 5:

Provide an @Autowired annotation on the GreetingServiceImpl's setter method, such as:

@Autowired
public void setMessageRepository(MessageRepository messageRepository) {
    this.messageRepository = messageRepository;
}

Then, add the 'annotation-config' element (from the new 'context' namespace) to your configuration:

<beans>
   
    <context:annotation-config/>

    <bean class="blog.GreetingServiceImpl"/>

    <bean class="blog.StubMessageRepository"/>

</beans>

Rerun the tests. They will still fail, but if you look closely it's a new problem. The assertions fail, because the messages being returned are null. That means that the 'messageRepository' property has been set on the greeting service! Now, the StubMessageRepository simply needs to be initialized.

Step 6:

Spring provides a couple options for initialization callbacks: Spring's InitializingBean interface or an 'init-method' declaration within XML. As of Spring 2.1, JSR-250 annotations are supported - providing yet another option: @PostConstruct (and the @PreDestroy annotation can be used for destruction callbacks as you will see shortly). In the StubMessageRepository, add the annotation to the initialize method:

@PostConstruct
public void initialize() {
    messages.put("English", "Welcome");
    messages.put("Deutsch", "Willkommen");
}

Rerun the tests. This time they should pass!

Step 7:

The @Autowired annotation can also be used for constructor-based injection. If you'd like to experiment with that option, remove the setter method from the GreetingServiceImpl and add this constructor instead (then rerun the tests):

@Autowired
public GreetingServiceImpl(MessageRepository messageRepository) {
    this.messageRepository = messageRepository;
}

If preferred, you can even use field-injection. Remove the constructor, add the annotation directly to the field, and rerun the tests. The code should look like this:

@Autowired
private MessageRepository messageRepository;

Step 8:

Add a JDBC-based repository implementation of the MessageRepository:

public class JdbcMessageRepository implements MessageRepository {

    private SimpleJdbcTemplate jdbcTemplate;

    @PostConstruct
    public void setUpDatabase() {
        jdbcTemplate.update("create table messages (language varchar(20), message varchar(100))");
        jdbcTemplate.update("insert into messages (language, message) values ('English', 'Welcome')");
        jdbcTemplate.update("insert into messages (language, message) values ('Deutsch', 'Willkommen')");
    }

    @PreDestroy
    public void tearDownDatabase() {
        jdbcTemplate.update("drop table messages");
    }

    public String getMessage(String language) {
        return jdbcTemplate.queryForObject("select message from messages where language = ?", String.class, language);
    }

}

Notice that in addition to @PostConstruct for initialization, this is using @PreDestroy to mark a method to be called on destruction. One thing is unclear from this implementation: how will the SimpleJdbcTemplate be provided? One option would be to provide a bean definition for the template. Another option would be to somehow provide a DataSource implementation to the template's constructor. Add the following (annotated) method:

@Autowired
public void createTemplate(DataSource dataSource) {
    this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
}

This demonstrates dependency injection working with an arbitrary method (not a traditional 'setter'). This will be tested in the course of the next step.

Step 9:

In Spring 2.1, "candidate" beans can even be discovered rather than provided explicitly in the XML as above. Certain annotations are recognized by default. This includes the @Repository annotation as well as a new @Component annotation. Add those two annotations to JdbcMessageRepository and GreetingServiceImpl respectively:

@Repository
public class JdbcMessageRepository implements MessageRepository {}
@Component
public class GreetingServiceImpl implements GreetingService {}

Then modify the XML file by removing the existing explicit bean definitions and simply adding a component-scan tag:

<beans>
    <context:component-scan base-package="blog"/>
</beans>

Then, add just the DataSource bean definition and the new tag for configuring property placeholders:

<beans>
    <context:component-scan base-package="blog"/>

    <context:property-placeholder location="classpath:blog/jdbc.properties"/>

    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

</beans>

… and the jdbc.properties file itself:

jdbc.driver=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:mem:blog
jdbc.username=sa
jdbc.password=

Rerun the tests, and you should see the green bar even though only the data source has been defined in XML.

Step 10:

Finally, add an aspect (the @Aspect annotations are also automatically detected by default):

@Aspect
public class ServiceInvocationLogger {

    private int invocationCount;

    @Pointcut("execution(* blog.*Service+.*(..))")
    public void serviceInvocation() {}

    @Before("serviceInvocation()")
    public void log() {
        invocationCount++;
        System.out.println("service invocation #" + invocationCount);
    }
}

And to activate automatic proxy generation, simply add the following tag to the xml:

<aop:aspectj-autoproxy/>

Rerun the tests, and you should see the log messages!

NOTE: the scanning and configuration process can be initiated without any XML and can be customized (e.g. detect your own annotations and/or types). I will discuss those features and more in the next post.

In the mean time, I hope this post will serve its purpose well - providing hands-on experience with these new Spring 2.1 features. As always, we are looking forward to feedback from the community, so please feel free to leave comments!

 

45 responses


  1. Really nice post, Spring 2.1 rocks..


  2. Great post!
    How is the scope of beans defined?


  3. I like these


  4. How does @Autowired relate to @Resource?


  5. The thing I always liked about Spring is that my sourcecode didn't depend on Spring. But I have the impression that this isn't as important for the Spring team anymore. Pojo's with annotations are not pojo's anymore.


  6. Peter - The nicer part is that Spring always gives you options (unlike some other frameworks). If you feel annotations intrude into your POJOs, you can always fallback on other options. I am still not very sure if we should remain so strict about the definition and interpretation of what constitutes a POJO, but localized metadata has some advantages. Of course there are issues like unit testing where I would not like to have Spring come along my way. It is interesting to find out what the Spring guys have to say about this.


  7. Great news! @PostCostruct and @PreDestroy are very useful annotations. Btw. how does spring 2.1 relate to PitchFork - http://interface21.com/pitchfork/ ?


  8. A little word of advice for anyone trying this out with @AspectJ annotations: Don't be lazy with your pointcuts. If your pointcut is "execution(* *.*(..))" it won't work. That's because the pointcut will also match the aspect class itself and you'll get a message stating that there's a circular reference. Just doing my part to save you the trouble I encountered.


  9. I like what Peter Veentjer said and from Martin Koci's post, I have a question: is there anyway to get rid of the @PostConstruct and @PreDestroy annotations in the Java file and declare it somewhere in the XML file?


  10. [quote comment="22970"]How does @Autowired relate to @Resource?[/quote]
    The @Resource annotation is also supported and can either resolve to a Spring-managed bean name (the default) or JNDI-name (for details, see: http://static.springframework.org/spring/docs/2.1.x/api/org/springframework/beans/factory/annotation/CommonAnnotationBeanPostProcessor.html).
    The @Autowired annotation can also be used for constructor-injection.


  11. [quote comment="22992"]Of course there are issues like unit testing where I would not like to have Spring come along my way.[/quote]

    Well one thing to remember is that annotations are just what you describe, metadata. Which means they have to be interpreted. So if you're running a true unit test, Spring isn't in the picture and the metadata is ignored. You do whatever injection you'd like as part of the test and Spring isn't around.


  12. [quote comment="22989"]The thing I always liked about Spring is that my sourcecode didn't depend on Spring. But I have the impression that this isn't as important for the Spring team anymore. Pojo's with annotations are not pojo's anymore.[/quote]
    I want to emphasize that the annotation-driven configuration is an optional mechanism. XML will of course always continue to be supported, and Java Configuration provides another non-XML based alternative in a completely non-invasive manner (http://www.springframework.org/javaconfig). The annotations can be used in combination with XML (as demonstrated in Step 9 above), and it is always possible to provide user-defined annotations instead of the Spring defaults (@Component, @Autowired, etc). In the next post, I will provide some examples of such customization options as well as using other criteria (assignable types, regular expressions, etc.) instead of annotations for the scanning.


  13. Let\'s also not forget that the Spring community aren\'t the only ones working on alternate configuration strategies. The grails folks have a groovy style of configuration that seems pretty cool: http://grails.codehaus.org/Spring+Bean+Builder


  14. The new annotation driven injection is awesome. I've been waiting for a way to automatically wire up everything programmatically instead of declaratively.

    From the example, one piece I see missing. Will there be a way to programmatically inject property values into fields?

    [quote post="160"]

    [/quote]

    To be replaced by something like…

    public class MyAppDataSource extends DriverManagerDataSource {

    @Autowired(propertyName="jdbc.driver")
    private setJDBCDriver(String jdbcDriver) {
    setDriverClassName(jdbcDriver);
    }

    … etc

    }


  15. I have the same question as Hideyuki Suzumi above; What about scopes?

    Looking forward to more great blog posts! :-) blog.interface21.com is really great.


  16. [quote comment="22993"]Great news! @PostCostruct and @PreDestroy are very useful annotations. Btw. how does spring 2.1 relate to PitchFork - http://interface21.com/pitchfork/ ?[/quote]
    At this point there isn't any direct connection as Pitchfork supports the EJB3 spec where the JSR250 annotations are used in a specific way (see the class and method annotations and inheritance rules that EJB 3 defines).
    Also, both @PostConstruct and @PreDestroy in EJB3 context, depend a lot on the interceptors enabled on a certain session bean as well as the defaults specified in the EJB3 container (through XML files).


  17. [quote post="160"]How is the scope of beans defined?[/quote]
    Currently, the scanned bean definitions will be singleton scope. Note however that the annotation-driven metadata can be merged with metadata in XML so that scope can still be provided in the XML (as well as any explicit properties).


  18. I think this is a great idea to have this on spring core.
    this is almost all that I did in the spring-annotations project …
    The only thing I do not understand is why when I suggested to merge spring-annotations with spring framework no one liked the idea, and now this is in the spring core …
    but as I said it is great to have this feature in the spring core.
    the only thing missing is the ability to choose the scope and other attributes for the scanned beans.

    PS.: not I think that the spring-annotation project is almost deprecated.


  19. the Spring-Annotations (http://sannotations.sourceforge.net) has the bean scanning feature, and it has support for defining scope and other bean properties in the annotation too.
    I have already suggested it before, but what do you think about merging the spring-annotations core (the engine with the annotations scanning, and some other things), with the Spring Framework?


  20. [quote post="160"]Currently, the scanned bean definitions will be singleton scope. [/quote]
    This is very inconvenient, I think.


  21. Yes, that`s why with spring-annotations you can choose which scope your scanned bean will be …
    and that was already working when I tried to submit that eature to spring last year, and they told me that it would never be in the spring core, because Spring is a DI container, and with this kind of annotation it will become a service lookup framework …

    and now they put it on spring core, without giving any credit to whom first told to do it …


  22. Currently, @Autowired and @Required cannot be specified on a class,
    though @Transactional can be specified on a class.
    I think it is useful if it is possible to apply to all setters at a time.


  23. Wouldn't it make sense to scan for @Configurable too?

    Or is that included in http://opensource.atlassian.com/projects/spring/browse/SPR-2492 ?


  24. Rodrigo,

    You wrote a similar question in this Jira entry:
    http://opensource.atlassian.com/projects/spring/browse/SPR-3486

    Mark has replied there, but I'll quote his reply:

    """Spring's annotation-driven configuration code has been introduced in the first milestone release of version 2.1. As a milestone release it will definitely continue to evolve, but it is in no way a "crippled" implementation. The implementation model we have chosen does not follow the approach of the spring-annotations project. We did not feel that mirroring the XML elements and attributes within annotations was the correct approach for our needs. We have a strong responsibility to provide support that will work in a complementary way with other Spring configuration options (including XML bean definitions as well as Java Config), and we are providing support for JSR-250 annotations with a clear focus on consistency. Since we are taking a different approach than the spring-annotations project, it did not make sense for us to consider re-using some of the spring-annotations code. As always, we welcome feedback from the Spring user community and for Spring users to build upon Spring in any way; it's great that people are trying to push the boundaries of what Spring can do. That said, after considerable thought and prototyping on how to best do annotation-driven dependency injection in a manner that is consistent with Spring in general, the Spring team decided this approach - implemented from scratch - was the best choice."""

    I think Mark's reply is pretty good on its own, but I can comment along the same lines. It's absolutely great the other projects try to build on Spring functionality to implement things that people need, and it's a testament to the flexibility of IoC, and how Spring was built, that it's possible to do this kind of stuff without having to modify Spring. However, that doesn't automatically mean when/if the core project tries to approach the same problem space it makes sense to reuse the same approach or even the code as somebody else may have used. Last year, while we had some decent experience in implementing annotation driven injection via the Pitchfork project, we first of all did not think it was the right time to do any sort of annotation driven injection in core Spring itself, and fundamentally the spring-annotation model didn't feel quite right either. This year, while we think many/most people will prefer to stick to XML, there is some demand for an annotation driven approach, and we're trying to meet this need (along with trying alternative Java-focused approaches like Java Config), in the fashion that feels best to us.

    I do think it's a bit disingenuous to try to imply that this new code uses or borrows from spring-annotation (with or without credit given). None of us have ever been in the code for spring-annotation, the model is pretty much different, this problem space has been tackled by other projects (EJB 3, our own Pitchfork, etc), and we've thought a lot about how to approach this, and hopefully have come up with a usable solution.

    Colin


  25. Of course I forgot to mention Bob Lee's Guice in my last paragraph above.

    Colin


  26. The other thing that needs emphasizing here (as Mark has said a few times) is that this stuff is going to continue to evolve. This is just an M1 release and this is just an initial cut of functionality that we feel pretty good about.

    For example, as Mark has said to me previously, it would take about a minute to support defining scope with an annotation, but right now we're not sure we necessarily think that's actually appropriate (should a bean really know about its own scope, is that not something for the deployer/configurer to worry about?). So for this release we've left scoping as something to be configured only via XML, which is actually quite easy to do…

    Colin


  27. [quote post="160"]should a bean really know about its own scope, is that not something for the deployer/configurer to worry about?[/quote]
    Why is @Autowired good?


  28. Why is there @ annotations for lifecycle methods instead of defining them by an interface?
    It usually allows the programmer to create methods as "stopp" or even "finalize".

    Such lifecycle interfaces are troublesome when they contain 10 methods, but a start/stop interface does not seem to hurt anyone and would allow all projects to have the same standard method names for such callbacks.

    Any thoughts?


  29. [quote post="160"]Why is there @ annotations for lifecycle methods instead of defining them by an interface?
    It usually allows the programmer to create methods as "stopp" or even "finalize".[/quote]

    Those lifecycle interfaces already exist. The org.springframework.beans.factory.InitializingBean interface contributes an afterPropertiesSet() method, the org.springframework.beans.factory.DisposableBean interface contributes a destroy() method, and the org.springframework.context.Lifecycle interface contributes isRunning(), start(), and stop() methods (typically used for objects dealing with threading).

    These interfaces are still detected and honored as they always have been by Spring, even when using the annotation scheme. The use of JSR-250 lifecycle annotations is just to add support for the JSE standard.


  30. To clarify on Ben's point about the JSR-250 annotations, these actually are a standard part of Java EE from Java EE 1.5 (last May), and then are included in Java SE 6 (JDK 1.6).

    Colin


  31. >> What do you think about AridPOJO-like xml configuration?

    Chris Richardson and I and a few of the other Interface21 people had a nice conversation at JavaOne. It was ironic that Chris came out with his article/implementation a few days before this stuff (above) made it into CVS as a first cut.

    It's an interesting approach to some of the same problems (i.e. trying to reduce XML). We've discussed (amongst ourselves, and with Chris), the use of AspectJ expressions to do filtering of stuff, in order to decide what to match on. In the fear of introducing too many approaches, we're going to hold off for the time being, but we're definitely going to try to work with Chris to get feedback on the best annotation driven approach.

    Btw, Chris is going to be presenting at SpringOne in Antwerp next month!

    Regards,
    Colin


    Attend SpringOne 2007, Interface21's developer conference covering the Spring Portfolio products.
    42 Sessions in 3 Parallel Tracks
    June 20 - 22, 2007 - Antwerp, Belgium
    www.springone.com


  32. (edited 2007-5-18 to fix typos and clarify)

    >>should a bean really know about its own scope, is that not something for the deployer/configurer to worry about?

    >Why is @Autowired good?

    Well it\'s not :-)

    Just kidding there… Now most of the Spring team do think that using the annotation approach is unnecessarily invasive, given the existence of alternative approaches (XML or the Spring Java Config) that are completely non-invasive. That said, there is definitely some demand for the annotation driven approach; some people know they want to use it, some people at least want to try it. So it\'s important that Spring offers best of breed options for XML, annotation, and external Java (aka Spring Java Config) based dependency injection.

    Anyway, @Autowire is one thing, it says, I expect somebody else will wire me. Setting your own scope takes things to another level. Arguably a bean might know about its appropriate scope sometimes, but other times it is clearly up to the deployer to pick. Think about an object that may be in a regular scope in some circumstances, and in Request or Session scope other times. What happens if you bake that into the object? We will almost certainly add the ability to apply scope via an annotation, but people need to be very careful in making the decision to actually use that annotation.

    Regards,
    Colin


  33. [quote comment=\"22963\"]How is the scope of beans defined?[/quote]
    Scope support has been added as of the latest 2.1-m2 snapshot (download here: http://static.springframework.org/downloads/nightly/snapshot-download.php?project=SPR)

    Scope can be determined from the value of the @Scope annotation (e.g. @Scope(\"request\")), and the default value is singleton.

    Please note that the ScopeMetadataResolver is a strategy interface, and custom implementations may be provided to the bean definition scanner (the default is AnnnotationScopeMetadataResolver).


  34. Hi Mark,

    First off, great work! I especially appreciate the support for the standard annotations defined by JSR 250, as that allows one to avoid too many dependencies on Spring APIs. Secondly, I have a few questions:

    1) When will the XSD file be available via http://www.springframework.org/schema/context/spring-context-2.1.xsd?
    My XML editor in Eclipse is bugging me about not being able to find the file. I added a custom entry to my XML Catalog in MyEclipse, and that serves as a nice work-around, but I imagine others will want the XSD available on the web soon as well. ;)

    2) Are you planning on adding support for multiple locations for the new context:property-placeholder tag? If not, I think that would be a nice add-on.

    regards,

    Sam


  35. Nice article to me.
    Thanks.


  36. [quote comment="23798"]Hi Mark,
    1) When will the XSD file be available via http://www.springframework.org/schema/context/spring-context-2.1.xsd?[/quote]

    The XSD is now available.

    [quote comment="23798"]
    2) Are you planning on adding support for multiple locations for the new context:property-placeholder tag? If not, I think that would be a nice add-on.[/quote]

    The 'location' attribute does actually accept a comma-delimited list of properties file locations (as Spring Resource locations).

    -Mark


  37. Mark,
    I left a question on the spring forums. Perhaps you can help me with that. It is related to your blog.
    http://forum.springframework.org/showthread.php?t=39018


  38. Good work! Expecting final release…


  39. I'm here for another vote on the annotations thing. It is very important to me, and central to my usage of Spring, that I have non-annotation options. The second I see one, I back off from that as a potential solution. Configuration and aspects have nothing to do with application code, isn't that the goal?


  40. @Debasish Ghosh

    Localized metadata defeats the purpose of extracting anything into a config. It's a very hard line, or it isn't one at all.

    @Colin

    If what you're giving us is a essentially a package-level configuration option then we should have the power to decide whether or not we want package-level scope definitions. An override method would be nice on some, but this has some powerful implications.

    I can create a package of beans I know will be prototyped and specify them as such. Because they will be such one-offs, I also autowire them into where they would be going..

    It seems like having this ability would really cut down on the amount of xml needed.

    Chris Richardson really got it 90% of the way there. I think its important to not forget his very practical initial implementation. Too much thinking and it starts veering off in an ivory tower direction.


  41. Hi Mark,

    Tried to run the code but failed to compile on @PostConstruct annotation. I am using Spring with "spring-framework-2.1-m2-with-dependencies.zip" download. Is this annotation work with the above mentioned version?

    Thanks Victor


  42. [quote comment=\"28688\"]Tried to run the code but failed to compile on @PostConstruct annotation.[/quote]

    Victor,

    You need to have the annotations within the \'javax.annotation\' package on the classpath. These are included in Java SE 6 - or if you are using Java 5, you can add the \'common-annotations.jar\' (in \'j2ee/lib\' of the distribution).


  43. Hi,
    should annotation-based AspectJ work with Java6? I keep getting an error about it, and I am running with Java6:

    [java] org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.aop.aspectj.AspectJPointcutAdvisor]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException: error the @annotation pointcut expression is only supported at Java 5 compliance level or above
    [java] Caused by:
    [java] java.lang.IllegalArgumentException: error the @annotation pointcut expression is only supported at Java 5 compliance level or above
    [java] at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:315)
    [java] at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:189)
    [java] at org.springframework.aop.aspectj.AspectJExpressionPointcut.checkReadyToMatch(AspectJExpressionPointcut.java:176)
    [java] at org.springframework.aop.aspectj.AspectJExpressionPointcut.getMethodMatcher(AspectJExpressionPointcut.java:162)
    [java] at org.springframework.aop.aspectj.AbstractAspectJAdvice.buildSafePointcut(AbstractAspectJAdvice.java:181)
    [java] at org.springframework.aop.aspectj.AspectJPointcutAdvisor.(AspectJPointcutAdvisor.java:51)
    [java] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    [java] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    [java] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    [java] at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    [java] at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:85)
    etc..


  44. Hi Mark,
    The cost of @Transactional seems very high. If I have a client that call a service that is annotated with @Transactional, it will at least required 300ms (this is relative) just to called the very simple method.
    While I don't really need a transactional method, but the problem is that I will get the "Session is closed" exception whenever I called something like this :
    em.read(); followed by em.merge(). It seems that without the @Transactional, I'm not able to use the em(EntityManager) more than once in one conversation.

    What is the best practice for this issue ? Can I avoid the @Transactional ? It has much better performance if I put the @Transactional at the caller side, but this is not I want.

    Thanks, and sorry if this is not the right place to ask :p


  45. dsfds fds

15 trackbacks

Leave a Reply