AspectJ advice not being detected in Spring application - spring-aop

I had an existing WAR with the following Spring (4.0.6.RELEASE) configuration:
<beans>
<context:annotation-config/>
<context:component-scan base-package="org.example"/>
</beans>
To this application I added the following annotation interface (copied verbatim):
package org.example;
#Documented
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.METHOD })
public #interface Logged {}
the following Aspect class (copied verbatim as well):
package org.example;
#Aspect
#Component
public class LoggingAspect
{
#Before("#annotation(Logged)")
public void before()
{
System.out.println("LoggingAspect.before()");
}
}
and the following batch processing class (copied verbatim):
package org.example;
#Component
public class Batch
{
#Logged
#Scheduled(fixedDelay = 100)
public void execute()
{
System.out.println("Batch.execute()");
}
}
The Spring configuration was then changed to:
<beans>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<context:annotation-config/>
<context:component-scan base-package="org.example"/>
<task:annotation-driven executor="executor" scheduler="scheduler"/>
<task:executor id="executor" pool-size="5"/>
<task:scheduler id="scheduler" pool-size="5"/>
</beans>
I was expecting to see the following messages on the console:
LoggingAspect.before()
Batch.execute()
However, I only see the second of these messages (that is, the aspect code is not being called).
I took out this code to a sample application and interestingly the two messages appear just fine in the sample app. I then compared every single file in the actual application with the sample and ensured that everything is exactly the same, including the class and file names. Yet, the aspect does not work in the actual application.
Upon turning on debug level logging in both applications, the sample application shows the following log message:
DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public void org.example.LoggingAspect.before()
but the actual application does not have this log message. This seems to indicate that the sample app detects the aspect method but the actual app does not. Both use the same Spring and AspectJ versions (4.0.6.RELEASE and 1.8.1 respectively). There are no errors in either log.
Spring instantiates LoggingAspect in both cases (gleaned from the logs).
I have also checked various JAR dependencies for the two apps and everything is the same, except that the actual app uses Spring ORM, Hibernate and EHCACHE JARs which the sample app does not.
Any pointers on what else should be checked will be useful.

Despite debugging the application for months, upgrading and degrading various Spring and AspectJ versions, the problem could not be resolved. Funnily enough, a sample application created out of the affected classes did not show any problems.
I had to finally circumvent the problem by specifying the aspect in the Spring configuration. The line:
<aop:aspectj-autoproxy proxy-target-class="true"/>
had to be changed to:
<aop:aspectj-autoproxy proxy-target-class="true">
<aop:include name="loggingAspect"/>
</aop:aspectj-autoproxy>
In this case loggingAspect is the default bean name assigned by the Spring framework to the instance of the bean class LoggingAspect. If the bean name is set to a different value, that value must be used with <aop:include />.

Related

IntelliJ - spring boot resources for ES6 configuration

I'm trying to make some simple project with AngularJs using ES6 with Traceur compiler and with Spring Boot as my backend. I already managed to configure my project so it works as I expected. I only have some problems with configuring IntelliJ to see my resources properly.
I put my static resources in src/main/resources/public and configure ResourceHandlerRegistry so that it redirects any unknown request to the main angular application file (I want to use html5 location mode, so it was necessary. I found working configuration in the second answer of this question Spring Boot with AngularJS html5Mode).
The error occurs when I import any of my ES6 modules:
import {appModule as app} from 'resources/app/main.js'; // <- here IntelliJ sees an error, it cannot find such file, but when I run the application it all works as expected
Here I uploaded my whole project: http://www.filedropper.com/spring-boot-test
Could anyone tell me what should I do to get rid of this error in IntelliJ or check what I've done wrong with my project?
btw. I use IntelliJ 14.
Edit:
I had error in StaticResourceConfigurator. It should be:
/* ... */
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/public/");
Instead of:
/* ... */
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/public/**").addResourceLocations("classpath:/resources/");
But it didn't solve my problem.

GAE : java.lang.NoClassDefFoundError: com/google/appengine/api/blobstore/BlobstoreServiceFactory

Kindly help me with this. I am using blob store for saving images and it is working perfectly fine on my local environment. But when I deploy the same code the cloud it is throwing me the exception : java.lang.NoClassDefFoundError: com/google/appengine/api/blobstore/BlobstoreServiceFactory
I am using GAE 1.8.4
Most likely, appengine-api.jar is missing from your war/WEB-INF/lib/ folder.
If you use Eclipse, click on the Problems tab. You may see a warning saying that this jar is not available on a server. Right click on this warning, select QuickFix, select "Copy..." option. Or copy this jar to this directory manually.
In my case the required jar was inside the WEB-INF/lib folder but the error was still occuring... I found that this error was occuring because Jetty 9 was not done yet with class loading startup process while one of my initialization class was requiring BlobstoreService:
public class InitializeAppContextListener implements ServletContextListener {
private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
So I had to postpone instance variable initialization once context is fully loaded as follow:
public class InitializeAppContextListener implements ServletContextListener {
private BlobstoreService blobstoreService;
public void contextInitialized(ServletContextEvent event) {
blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
Then the webapp was able to start normally again. This new behavior appeared after we had upgraded from servlet-api 2.5 to 3.1 with JDK 1.8...

App Engine, Android Studio, Generate Endpoint "No JPA #Entity Class found in MessageData2.java"

this is a regression. Earlier (than Jan 2014) versions of Android Studio would successfully generate the Endpoint code from a model.
steps: New Project, Tools > Generate App Engine, select any of the endpoint models (DeviceInfo or Message) or add a class file (with #Entity etc). Tools> Generate Endpoint
gets: No JPA #Entity Class found in MessageData2.java in dialog box Failed to Generate Endpoint Class
expected: code generation as in the past
update: rolled back to 0.4.2 (it used to work) and yikes! still getting Dialog Box (really stuck now).
update [not stuck anymore]: rolled back MAVEN to 3.0.5, built new clean project, app{appname}-endpoints succesfully built, then Generate Endpoint worked (still has the bug where client code is not copied to endpoint directory, look for it in {appname}-AppEngine/target and copy by hand to {appname}-endpoint tree
i logged a bug through App Studio to https://code.google.com/p/android/issues/detail?id=65270 if you want to track
(answer from comment on https://code.google.com/p/android/issues/detail?id=65270 )
Tools>Generate Endpoints will work in 0.4.3 by adding this code to pom.xml
trevorjohns#google.com :"
I ran into this problem recently. Adding:
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
</dependency>
to my backend pom.xml seemed to fix it."
yes, fixed!

How can I configure the JAX-RS base path in TomEE+?

I have a WAR with some JAX-RS services, deployed into TomEE Plus. Given a service annotated with #Path("myservice"), TomEE+ publishes it to localhost:8080/mywebapp/myservice.
However, that also makes accessing a JSP at localhost:8080/mywebapp/index.jsp impossible - JAXRSInInterceptor complains that No root resource matching request path has been found, Relative Path: /index.jsp.
So I would like to configure a path prefix api to all services, which changes the myservice URL to localhost:8080/mywebapp/api/myservice. Doing so would be trivial if I had configured CXF on my own (with or without Spring), because I could simply change the URL pattern of the CXF Servlet - but I am relying on the default settings where I don't configure anything besides the annotations. So how do I do that in this case?
Note that I don't want to alter the #Path annotations to include the prefix, because that does not fix the issue with the JSP.
Create an extension of javax.ws.rs.core.Application and annotate it with #ApplicationPath where value would be api in your case:
#ApplicationPath("/api")
public class MyApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<Class<?>>();
// register root resource
classes.add(MyServiceResource.class);
return classes;
}
}
This way a Servlet 3 container would find your application and map your resource to /mywebapp/api/myservice while making your web resources (.jsp) available at /mywebapp.
TomEE trunk supports these configurations: cxf.jaxrs.staticSubresourceResolution & cxf.jaxrs.static-resources-list
but the #ApplicationPath is the more relevant solution IMO
Using -Dopenejb.webservice.old-deployment=true can help too in some cases

Weld CDI on Google App Engine: Injection in servlet not happening

This is my first time working with GAE and I'm trying to get CDI working. Long story short: The #Inject field in my servlet is not getting injected (it's always null).
I'm working in Eclipse and debug the application on the local test server included in the GAE SDK (which is started by Eclipse as well). When I access the servlet on localhost, I get a null-pointer exception for someService. I've also output the value of someService to verify it is really null, which it is.
Edit: When I added a #Named("skldjfx") qualifier to the injection point, Weld complained the dependency is unsatisfied (in the validation phase), so that's a good sign. However, the field is still always null.
Servlet:
public class BlogServlet extends HttpServlet {
#Inject private SomeService someService;
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/plain");
resp.getWriter().println("Hello. " + someService.getSomeValue());
// \
// always null
}
}
SomeService class:
#ApplicationScoped
public class SomeService {
private String someValue = "some value";
public String getSomeValue() {
return someValue;
}
}
I've configured Weld's Listener in web.xml:
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
The listener is properly loaded because it logs its initialization message: org.jboss.weld.environment.servlet.Listener contextInitialized.
I've included (an empty) beans.xml in both war/WEB-INF and war/META-INF. I also tried it without META-INF. Maybe beans.xml isn't processed? Other contents in the WEB-INF folder (such as web.xml) are processed properly.
How can I verify if beans.xml is processed and/or fix SomeService not getting injected?
It looks like it's not possible to use CDI with GAE, because GAE's Jetty fork ignores jetty-web.xml, which is needed to specify the BeanManager. See this link and this link. Really strange GAE is not supporting the use of CDI.
Note that these links are really old, but so far I haven't found any evidence to the contrary.
Anyway, my next step will be to use Google's own dependency injection framework Guice. Using it with GAE is described here. I'd prefer CDI though.

Resources