0

I went through all the possibilities trying to make my project running on Tomcat and point cut the model (getters) and woven them using AspectJ Load Time Weaver. Basically, I followed all the steps in the Spring Documentation http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-atconfigurable. I also followed the same approach mentioned Lazy/Eager loading/fetching in Neo4j/Spring-Data. My project is divided in two main project: - core: spring-data-neo4j (repository and configuration), domain-model in a dedicated package, LoggingAspect and LazyLoadingAspect. p.s. I am not using any configuration in XML files. I am using Annotation purely. - content: web application running on Tomcat which depends on core project and I want to weave when I invoke getter methods in the domain project.

Running the core itself I managed to get it running using maven plugin and adding the dependencies for aspectj. But all the hell starts when I move to Tomcat. I tried all the possibilities e.g using -javaagent, create the custom context.xml, put spring-instrument into tomcat/lib folder, etc etc. I am receiving the following exception:

java.lang.IllegalStateException: Post-processor tried to replace bean instance of type [com.test.server.graph.domain.model.Sequence] with (proxy) object of type [org.springframework.beans.factory.aspectj.$Proxy96] - not supported for aspect-configured classes!
    at org.springframework.beans.factory.wiring.BeanConfigurerSupport.checkExposedObject(BeanConfigurerSupport.java:173)
    at org.springframework.beans.factory.wiring.BeanConfigurerSupport.configureBean(BeanConfigurerSupport.java:143)
    at org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect.configureBean(AnnotationBeanConfigurerAspect.aj:63)
    at org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect.ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(AbstractDependencyInjectionAspect.aj:88)
    at com.test.server.graph.domain.model.Sequence.(Sequence.java:29)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at org.neo4j.ogm.annotations.EntityFactory.instantiate(EntityFactory.java:135)
    at org.neo4j.ogm.annotations.EntityFactory.instantiateObjectFromTaxa(EntityFactory.java:110)
    at org.neo4j.ogm.annotations.EntityFactory.newObject(EntityFactory.java:61)
    at org.neo4j.ogm.context.GraphEntityMapper.mapNodes(GraphEntityMapper.java:147)
    at org.neo4j.ogm.context.GraphEntityMapper.mapEntities(GraphEntityMapper.java:132)
    at org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:107)
    at org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:102)
    at org.neo4j.ogm.context.RestModelMapper.mapEntity(RestModelMapper.java:157)
    at org.neo4j.ogm.context.RestModelMapper.map(RestModelMapper.java:76)
    at org.neo4j.ogm.session.delegates.ExecuteQueriesDelegate.query(ExecuteQueriesDelegate.java:94)
    at org.neo4j.ogm.session.delegates.ExecuteQueriesDelegate.query(ExecuteQueriesDelegate.java:73)
    at org.neo4j.ogm.session.Neo4jSession.query(Neo4jSession.java:313)
    at org.springframework.data.neo4j.template.Neo4jTemplate.query(Neo4jTemplate.java:217)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
    at com.sun.proxy.$Proxy58.query(Unknown Source) 

pom.xml (core.project)

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-neo4j</artifactId>
        <version>${sdn.version}</version>
    </dependency>
    <dependency>
        <groupId>org.neo4j</groupId>
        <artifactId>neo4j-ogm-core</artifactId>
        <version>2.0.3-SNAPSHOT</version>
    </dependency>

My Configuration class (core project)

@org.springframework.context.annotation.Configuration
@ComponentScan(basePackages = "org.test.server.graph")
@EnableNeo4jRepositories(basePackages = "org.test.server.graph.repository")
@EnableAspectJAutoProxy
@EnableSpringConfigured
public class Neo4jConfig extends Neo4jConfiguration { 
    @Bean
    public Configuration getConfiguration() {
        Configuration config = new Configuration();
        config.driverConfiguration().setDriverClassName("org.neo4j.ogm.drivers.http.driver.HttpDriver")
                .setURI(System.getProperty("neo4j.host")).setCredentials(System.getProperty("neo4j.user"),System.getProperty("neo4j.password"));
        return config;
    }

    @Bean
    public SessionFactory getSessionFactory() {
        return new SessionFactory(getConfiguration(), "org.test.server.graph.domain" );
    }

    @Bean
    @Scope(value = "prototype")
    public Session getSession() throws Exception {
        return super.getSession();
    }
}

Domain-model classes

As recommended by Spring Documentation I annotated the classes in the Domain model

@Configurable

mvc-dispatcher-servlet (webapp project)

<context:spring-configured />
<context:load-time-weaver aspectj-weaving="on" weaver-class="org.springframework.instrument.classloading.tomcat.TomcatLoadTimeWeaver" />

I tried running using tomcat-maven-plugin and tomcat standalone installation (v7 and v8).

-- UPDATE --

Sequence.java

@NodeEntity
@Configurable
public class Sequence extends DatabaseObject {

    @Relationship(type = "hasModifiedResidue", direction = Relationship.OUTGOING)
    private List<AbstractModifiedResidue> hasModifiedResidue;

    @Relationship(type = "referenceEntity", direction = Relationship.OUTGOING)
    private ReferenceSequence referenceEntity;

    public Sequence() {}

   //getter and setters

}

DatabaseObject.java

@NodeEntity
@Configurable(
    preConstruction = false
)
public abstract class DatabaseObject implements Serializable, Comparable<DatabaseObject> {

    @GraphId
    private Long id;

    // other common attributes + getter and setters, no more annotation

LazyLoadingAspect

@Aspect
@Component
public class LazyFetchAspect {

    @Autowired
    private Neo4jOperations neo4jTemplate;

    @Around("modelGetter()")
    public Object autoFetch(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println(" Testing Aspect ");

        return pjp.proceed();
    }

    @Pointcut("execution(public * com.test.server.graph.domain.model.*.get*(..))")
    public void modelGetter() {
    }
}
Community
  • 1
  • 1
Gui
  • 72
  • 9
  • My guess would be that AspectJ load-time weaving is not working when you run things under Tomcat. I think you should verify that load-time weaving does actually take effect and fix your configuration until it does. You could also consider using compile-time weaving (you can do it with maven and you can have Eclipse use the AspectJ compiler too). I had great success using `@Configurable` with compile-time weaving. Try running the Tomcat JVM with the `-javaagent` vm argument. – Nándor Előd Fekete Jun 14 '16 at 23:29
  • Also, you should enable debug logging for the AspectJ load-time weaver, so you could actually see what it's doing. See my [answer](http://stackoverflow.com/a/35224749/2699901) on an unrelated question for details on how to do it. – Nándor Előd Fekete Jun 14 '16 at 23:34
  • @NándorElődFekete. The core project itself is working and I can see the output "Testing Aspect" when executing. Two thing for you to take into account, I am running IntelliJ which shouldn't be a problem and I am running tomcat using with the -javaagent. I will enable debug logging and I will come up with updates. Cheers. – Gui Jun 15 '16 at 08:10
  • I guess you're seeing the "Testing Aspect" message when running your project NOT under Tomcat. That's good, but it doesn't mean that LTW is working under Tomcat. Maybe try removing the `weaver-class="org.springframework.instrument.classloading.tomcat.TomcatLoadTimeWeaver"` attribute from the `` configuration tag. – Nándor Előd Fekete Jun 15 '16 at 15:46
  • @NándorElődFekete. That's what I tried after posting here! Hopefully it is working now. I will come up with a cleaner version and post the solution here. – Gui Jun 16 '16 at 13:13
  • @NándorElődFekete Thank you guys for all of your help here. – Gui Jun 16 '16 at 13:14

1 Answers1

0

The main problem seems to be that you are applying aspects to beans:

Post-processor tried to replace bean instance of type [com.test.server.graph.domain.model.Sequence] with (proxy) object of type [org.springframework.beans.factory.aspectj.$Proxy96] - not supported for aspect-configured classes!

This wont work, so you have to make sure your model classes are real POJOs and not beans and exclude them from spring. (Make sure that in domain.model.* there is no spring annotation) - maybe if you post your Sequence.java I can see what might be causing the conflict.

On the other hand you have to make sure that aspectj is only assigned to the models and not any beans. So make sure you have a /META-INF/aop.xml that only includes your pojo models:

<!DOCTYPE aspectj PUBLIC
        "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
    <aspectj>
        <weaver>
            <!-- only weave classes in our application-specific packages -->
            <include within="com.test.server.graph.domain.model.*" />
        </weaver>
        <aspects>
            <!-- weave in just this aspect -->
            <aspect name="my.util.aspects.Neo4jFetchAspect" />
        </aspects>
    </aspectj>

Parts of my pom.xml (i have a different setup by now - thats why the spring version is so old):

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.6.12</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.6.12</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>3.1.1.RELEASE</version>
    </dependency>

I dont have any special build plugins or similar

Niko
  • 6,133
  • 2
  • 37
  • 49
  • Thanks for your reply. I have added the Classes as an update in the main question. The @Configurable on it, is because Spring Documentation says. The model has Neo4j annotation (SDN4) and I want to LTW them in order to apply the LazyLoading. My graphDB is really huge in depth, if I get them all for a given entity it will last forever. – Gui Jun 14 '16 at 10:15
  • @Guilherme It might be the configurable thats the problem. I am pretty sure you cannot mix that. What happens when you remove the annotation and make sure spring doesnt reach this class? – Niko Jun 14 '16 at 12:18
  • I get NoSuchMethodError. What are the dependencies in your pom.xml ? Or what kind of configuration do you use ? – Gui Jun 15 '16 at 12:26
  • Thank you guys for all of your help here. I credit this to you. – Gui Jun 16 '16 at 13:15
  • @Guilherme thanks and great that we could help - can you update you question with what the actual solution/problem was - in case others stumble upon this problem? – Niko Jun 16 '16 at 16:27
  • Sure, I will do that, I am just cleaning up my code now and I will come up with a clear solution - this is on my track. Thanks for pointing this out! – Gui Jun 17 '16 at 09:13