I have an aspect which works fine when I run it from a unit test or through a stand alone application. However when I run it as a part of web application and host it on Tomcat the Aspects are not applied.
My aspect looks like
public class MyAspect {
#Around("within(com.service..*)")
public Object doLogging(ProceedingJoinPoint pjp) throws Throwable {
//do something
Object obj = pjp.proceed();
//do something else
return obj;
}
}
I am able to solve this. The reason was that the aspect were getting processed by web application context and not by global application context so I have to restructure couple of things. I have detailed the steps here
#seanizer Spring does support within. It's true that it is only applied to methods and in within it will apply to methods of all the package and sub package of com.service. For details check the reference documentation here
Update: I'll leave this in, because it's still partially valid, even if it didn't help in your case. I'll edit a few places though, edits are marked like this or this.
If you're using Spring AOP, it can't work. Spring AOP only fully supports the execution pointcut. The within pointcut only works when it applies to method executions, for the full functionality of within you will need AspectJ (Spring AOP only uses some AspectJ pointcuts, but not the AspectJ weaver). Either through static compilation (usually through Maven or Ant) or through Load-Time-Weaving.
Also, your class is missing an #Aspect annotation.
How about move
<context:component-scan base-package="com.*" />
<mvc:annotation-driven/>
<aop:aspectj-autoproxy />
to servlet-mvc.xml?
Related
I have an issue with #Cacheable and #CacheEviction annotations. When I call these methods in the bean where they are declared, the aop part is not getting executed.
The underlying reason for this is that the bean access to its own instance itself, instead of accessing the spring proxy.
I have read this question where it is said that in most cases it should not be necessary a bean accessing the proxy.
Probably those answers work for me. The question is:
Is there any other way to make annotated methods work? Or does it sound like I found a good reason for a bean needing to access the proxy itself?
As is well documented in the Spring user manual, self-invocation cannot work with Spring AOP because Spring AOP uses proxies. So if you want to make self-invocation trigger an aspect, please switch to full AspectJ via LTW (load-time weaving). It works with the original beans and does not use any proxies.
Update: If you want to avoid using native AspectJ and instead as a (pretty lame and anti-AOP) workaround want to make your component proxy-aware, of course you can use self-injection and reference the cached method using the auto-wired proxy like this:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
#Component
public class MyComponent {
#Autowired
MyComponent myComponent;
public void doSomething() {
System.out.println(myComponent.doCacheable());
System.out.println(myComponent.doCacheable());
System.out.println(myComponent.doCacheable());
}
#Cacheable("myCache")
public String doCacheable() {
return "" + System.nanoTime();
}
}
Calling doSomething() on the MyComponent bean should yield output like this:
247760543178800
247760543178800
247760543178800
This proves that caching works like this. If instead you just have three lines of either System.out.println(doCacheable()); or the weird, nonsensical variant from the other (now deleted) answer
System.out.println(MyComponent.this.doCacheable());, then you would get three different values on the console, i.e. nothing would be cached.
I'm implementing an AOP-based caching layer similar to Spring Cache, and I'm having trouble getting my advice to execute when the joinpoint is called by another method in its own class. I was initially using Spring AOP's AspectJAutoProxy, and I understand why that doesn't allow for this use case, so I tried switching to AspectJ's load-time weaver, but it doesn't appear to have done anything. Here are all the details:
Spring version: 4.5.2
AspectJ version: 1.8.9
Java agent(s) added to run command. Note that I've tried including each of the two agents separately and together, without any difference in behavior:
-javaagent:/var/app/cops/jars/aspectjweaver-1.8.9.jar -javaagent:/var/app/cops/jars/spring-instrument-4.3.0.RELEASE.jar
Application entrypoint:
#Configuration
#EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
public class Application implements ApplicationContextAware {
#Bean
public InstrumentationLoadTimeWeaver loadTimeWeaver() throws Throwable {
InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
return loadTimeWeaver;
}
// Other unrelated beans
}
Advice signature:
#Around("#annotation(cacheable)")
public Object processCacheable(ProceedingJoinPoint joinPoint, Cacheable cacheable) throws Throwable
Method signature:
#Cacheable(key = "'test-key'")
public Map<String, Object> getDataFromSource()
"processCacheable" gets executed before "getDataFromSource" is called by another class, but still not if called from within the same class. Is there some configuration I'm missing in order to get LTW working correctly?
My usual disclaimer: I am not a Spring user. So I have next to zero experience with Spring configuration. But having looked at the weaving agent you put on your command line, I cannot find any AspectJ-related stuff in there. It is a really small JAR with only instrumenting classes that seem to rely on other transformers/weavers being deployed and somehow configured in your container.
I suggest you put the actual AspectJ weaving agent on your command line and see what happens. ;-)
Update: Or you if that does not help try both agents on the command line at the same time. I cannot tell you exactly what spring-instrument does, but I think it somehow integrates aspectjweaver (which does the actual aspect weaving) deeper into the Spring framework, even though AspectJ would also work without Spring even knowing of its existence.
I've run into a strange problem that I am having difficulty tracking down. I have an class (ServiceErrorInterceptor) defined as an #Aspect which is instantiated via XML configuration as a singleton bean. The XML configuration allows me to inject its dependent beans.
In my normal workflow, everything works fine. The aspect class is properly instantiated, and whenever the advice is called, the injected beans are as I would expect.
However, when I run my JUnit test, all my injected beans are null. This leads me to the conclusion that the advice is called from a different bean - not the same singleton bean that was instantiated by Spring. To further validate my hypothesis, I put a breakpoint on a setter which is called during the instantiation, and see that the bean id is not the same as the bean id if I put a breakpoint in my advice.
Is there some special configuration I must enable in my JUnit class to rectify this? My test class is already annotate with:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {
"classpath:spring/applicationContext-base.xml",
"classpath:spring/applicationContext-calculateServices.xml",
"classpath:spring/applicationContext-dom.xml"})
public class LendingSimulationServiceImplTest {
...
...
}
I've looked through the logs (I enabled spring trace logs), but don't see anything that stands out. And posting the entire log here would likely be overkill. If there is value in a specific part of the log please let me know and I will post it.
I'm able to post my code for the aspect, my junit and my config if that is helpful.
application-context.xml snippet:
<!-- SPRING ASPECT BEAN. POINTCUT DEFINED IN BEAN WITH ANNOTATION -->
<bean id="serviceErrorInterceptor" class="com.cws.cs.lendingsimulationservice.error.ServiceErrorInterceptor" scope="singleton">
<property name="errorMessageProvider" ref="resourceBundleProviderImpl"/>
<property name="defaultLocale">
<util:constant static-field="java.util.Locale.ENGLISH" />
</property>
</bean>
Any suggestions would be appreciated.
EDIT
My bean is implemented as:
#Aspect
public class ServiceErrorInterceptor {
/**
* Logger
*/
private static final Logger logger = LoggerFactory.getLogger(ServiceErrorInterceptor.class);
/**
* SOAP Header data
*/
#Autowired
private SOAPHeaderData soapHeaderData;
public ServiceErrorInterceptor(){
int x = 0;
x=x+1;
}
/**
* Exception Interceptor.
* #param ex
*/
#AfterThrowing(pointcut = "execution(* com.cws.cs.lendingsimulationservice.process.CalculatorProcess.calculate (..))", throwing = "ex")
public void errorInterceptor(Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error Message Interceptor started");
}
}
The relevant portions of my pom:
<!-- Aspect Oriented Programming (AOP) Framework (depends on spring-core,
spring-beans) Define this if you use Spring AOP APIs (org.springframework.aop.*) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Support for AspectJ Annotations -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${org.aspectj}</version>
</dependency>
I've done further debugging and putting a breakpoint in the dummy constructor, I get the following results:
with #Aspect and XML configuration, the constructor is called twice (different bean ids)
if I remove the #Aspect annotation then it is only called once.
If leave the #Aspect but remove the XML configuration, then the constructor isn't even called.
If I use an #Component annotation in combination with #Aspect (but without any XML configuration), then the bean is constructed twice.
Oddly enough, however, with both the #Component and #Aspect annotations AND the XML configuration, the constructor is still only called twice.
So then why would having both the XML configuration and the #Aspect annotation cause the constructor to be called twice with two different bean ids?
I have further validated that if I move the entire AOP definition into the XML configuration (removing the #Aspect and #Pointcut annotations) then the bean is only constructed once.
END EDIT
Thanks,
Eric
Does your aspect by any chance have any of the autodetect annotations (#Component, #Service) etc, apart from #Aspect - if it does, that could be one reason why a different bean seems to be present along with the one defined in your configuration.
Also, just scan through all your configuration to make sure that you are not declaring this bean elsewhere.
There is nothing special that needs to be done at the Junit level that I am aware of.
After a lot of discussion with the folks over at the SpringSource STS forum (see this thread), it turns out that the issue is related to the AJDT configuration. At the moment, AJ is weaving in the aspect, and Spring is locating the aspect on the Classpath, so they are both being executed.
Unfortunately, the AJ maven plugin is missing a configuration parameter to allow for exclusion of weaving; the current configuration excludes both LTW and CTW.
So, the workaround at the moment is to add -xmlConfigured to the AJ compiler flags and then specify an aop.xml file in aop.xml management which only lists the AJ aspects that you want to include in the project.
To get this to work, add '-xmlConfigured' to the Project Properties
'Non-standard compiler options' and then in AspectJBuild>'aop.xml
management' point it at a simple aop.xml file:
<aspectj>
<aspects>
<aspect name="com.fooMyNewNoneSpringAspect"/>
</aspects>
</aspectj>
Thanks to Andy Clement at the STS forum for this discovery and workaround. He will be raising JIRA issues to further address this shortcoming in the maven plugin.
A possible way you might find yourself in the same situation: you used the new operator rather than letting Spring inject your service.
Remember, we're not in AspectJ compile time weaving here. Nope, we're using Spring AOP proxies, so Spring must instantiate the object and dress it with proxies. If you were silly, like myself, and created a new service inside your tests, you won't get any AOP.
All the more reason to do compile time weaving with AspectJ and skip over all of the drawbacks of Spring AOP such as runtime weaving startup delay, inability to weave non-public and non-final classes.
I'm studying Spring 3 and I'm using it in a simple web-application.
Now I'm implementing a Spring MVC Controller using annotations, and I'm wondering:
Is there any best practice using #RequestMapping annotation?
I mean: I've seen that usually the URL mapped in this annotation is hardcoded in the class...
Is there a way to pass the URL in a 'loosely coupled way' (to obtain a more reusable class)?
I know that there are some wild cards that can be used, but I think that isn't the solution... Am I wrong?
EDIT:
I add an example to better explain my doubt.
Suppose I want my controller to be triggered by a request to /foo/bar/baz/mypage.htm, in my controller the handler method will be annotated with #RequestMapping("/foo/bar/baz/mypage").
Now I decide to change the URL triggering my controller into /foo/bar/otherpage.htm, so i need to edit my class, put #RequestMapping("/foo/bar/otherpage") on my handler method, recompile the project and deploy it again.
It seems to me not so practical...
Currently annotated controllers aren't very configurable.
As far as I know, the only possible approach to this problem is to use alternative HandlerMappings in order to configure "base URLs" of controllers. For example, as follows:
// Note the absense of #Controller to prevent this controller
// from being discovered by DefaultAnnotationHandlerMapping
public class FooController {
#RequestMapping("/list") public String list(...) { ... }
#ReqeustMapping("/save") public String save(...) { ... }
}
.
<bean
class = "org.springframework.web.servlet.mvc.support.ControllerBeanNameHandlerMapping" />
<bean name = "/foo" class = "FooController" />
<bean name = "/bar" class = "FooController" />
In this example two instances of FooController handle /foo/list, /foo/save, /bar/list and /bar/save respectively.
The upcoming Spring 3.1 will have an improved Spring 3.1 architecture (Spring 3.1 M2: Spring MVC Enhancements) that seems to be more flexible, though I haven't checked it yet.
I think you are trying to solve the wrong problem. If you wanted to change the pages that matched a controller you'd need to change a file somewhere. Would you rather change the file with the related code underneath it, or would you rather work with some XML files that specifies the URL and the class, and then you have to worry about the file being in the right place during runtime?
As there should be almost no code in your controller anyway, you should think of your controllers as compilable configuration files. Also, if you are using a build system like Maven or Ant and not compiling individual files by hand using Javac then compilation time shouldn't be an issue. If it becomes one, it's probably time to split your project into sub-projects.
I think you should just embrace this and see that it is probably not the issue you think it is. Also, did you know that controllers can match to expressions and not just literal strings? That gives you some flexibility in your naming.
If you really want to, you could just fall back to the Spring 2.0 style XML configuration, but I don't think anyone would recommend that.
I think that is not a best practice, but have you tryed with #PathVariable annotations?
#RequestMapping(value="/path/{word}", method=RequestMethod.GET)
public ModelAndView myRestMethod(#PathVariable String word) {
...
}
I've been trying to get a sample JMX MXBean working in a Spring-configured webapp, but any basic attributes on the MXBean are coming up as UNDEFINED when I connect with jconsole.
Java interface/classes:
public interface IJmxBean { // marker interface for spring config, see below
}
public interface MgmtMXBean { // lexical convention for MXBeans - mgmt interface
public int getAttribute();
}
public class Mgmt implements IJmxBean, MgmtMXBean { // actual JMX bean
private IServiceBean serviceBean; // service bean injected by Spring
private int attribute = 0;
#Override
public int getAttribute() {
if(serviceBean != null) {
attribute = serviceBean.getRequestedAttribute();
}
return attribute;
}
public void setServiceBean(IServiceBean serviceBean) {
this.serviceBean = serviceBean;
}
}
Spring JMX config:
<beans>
<context:component-scan base-package="...">
<context:include-filter type="assignable" expression="...IJmxBean" />
</context:component-scan>
<context:mbean-export />
</beans>
Here's what I know so far:
The element is correctly instantiating a bean named "mgmt". I've got logging in a zero-argument public constructor that indicates it gets constructed.
is correctly automatically detecting and registering the MgmtMXBean interface with my Tomcat 6.0 container. I can connect to the MBeanServer in Tomcat with jconsole and drill down to the Mgmt MXBean.
When examining the MXBean, "Attribute" is always listed as UNDEFINED, but jconsole can tell the correct type of the attribute. Further, hitting "Refresh" in jconsole does not actually invoke the getter method of "Attribute"- I have logging in the getter method to indicate if it is being invoked (similar to the constructor logging that works) and I see nothing in the logs.
At this point I'm not sure what I'm doing wrong. I've tried a number of things, including constructing an explicit Spring MBeanExporter instance and registering the MXBean by hand, but it either results in the MBean/MXBean not getting registered with Tomcat's MBean server or an Attribute value of UNDEFINED.
For various reasons, I'd prefer not to have to use Spring's #ManagedResource/#ManagedAttribute annotations.
Is there something that I'm missing in the Spring docs or MBean/MXBean specs?
ISSUE RESOLVED: Thanks to prompting by Jon Stevens (above), I went back and re-examined my code and Spring configuration files:
Throwing an exception in the getAttribute() method is a sure way to get "Unavailable" to show up as the attribute's value in JConsole. In my case:
The Spring JMX config file I was using was lacking the default-autowire="" attribute on the root <beans> element;
The code presented above checks to see if serviceBean != null. Apparently I write better code on stackoverflow.com than in my test code, since my test code wasn't checking for that. Nor did I have implements InitializingBean or #PostConstruct to check for serviceBean != null like I normally do on almost all the other beans I use;
The code invoking the service bean was before the logging, so I never saw any log messages about getter methods being entered;
JConsole doesn't report when attribute methods throw exceptions;
The NPE did not show up in the Tomcat logs.
Once I resolved the issue with serviceBean == null, everything worked perfectly. Regardless, +1 to Jon for providing a working demo, since there are literally 50 different ways to configure MBeans/MXBeans within Spring.
I've recently built a sample Spring based webapp that very cleanly enables JMX for latest versions of Spring, Hibernate and Ehcache.
It has examples for both EntityManager based access and DAO access (including transactions!). It also shows how to do annotation based injection in order to negate having to use Spring's xml config for beans. There is even a SpringMVC based example servlet using annotations. Basically, this is a Spring based version of a fairly powerful application server running on top of any servlet engine.
It isn't documented yet, but I'll get to that soon. Take a look at the configuration files and source code and it should be pretty clear.
The motivation behind this is that I got tired of all of the crazy blog posts with 50 different ways to set things up and finally made a single simple source that people can work from. It is up on github so feel free to fork the project and do whatever you want with it.
https://github.com/lookfirst/fallback