Search code examples
javajbossaopaspectjspring-aop

AspectJ load time Weaving not working properly within EAR deployed classes


I'm working on a multimodule project composed by many WAR files. The projects use Spring 4.0.5 for managing dependencies and AspectJ 1.8.5 with load time weaving to support AOP (Spring basic AOP support is not enogh in this project). Also, there are an aop.xml in the META-INF directory with very simple configuration:

<aspectj>
  <aspects>
   <!--No need to specify any aspect here-->
  </aspects>
  <weaver options="-XnoInline -verbose">
    <include within="com.myproject..*" />   
  </weaver>
</aspectj>

AOP is used mainly to provide various services and DAOs (anotated with @Service and @Repository) with Transactional behaviour (with spring's @Transactional annotation). For example:

@Service(value = "alertService")
public class AlertServiceImpl implements IAlertService, Serializable {
  ...
  @Transactional(rollbackFor = Exception.class)
  @Override
  public Alert createAlert(Alert alert) {
    alertDAO.create(alert);
    return alert;
  }
  ...
}

Or an abstract Base DAO from which the rest of application's DAOs inherit

@Repository
public abstract class BaseDAO<E extends IBusinessObject, PK extends Serializable> {
  ...
  @Transactional(readOnly = true)
  public <C extends E> C findFirstByFields(Class<C> type, String[] fields, Object[] values, String[] dependencies)
      throws ModelException {
    List<C> list = findAllByFields(type, fields, values, null, null, 1, null);
    if (list.isEmpty()) {
      return null;
    } else {
      C obj = list.get(0);
      loadDependencies(obj, dependencies);
      return obj;
    }
  }
  ...
}

Finally the project uses maven for building and runs on JBoss EAP 6.1.

So with this configuration everything works fine when building and deploying WAR files. But if i build a simple EAR file only with one of those WAR files inside, load time weaving weaves all clases but one, the BaseDAO.

I've been struggling with this for many time and the only thing i can get is that on application boot, weaving works almost equal in both cases except that within the EAR, BaseDAO is not weaved. I can't figure out why. Any idea of why this is happening?

P.D.: Enabling AspectJ weaving log shows this when booting application from a WAR:

 ...
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.commons.services.CommonService$AjcClosure1'
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.commons.services.CommonService$AjcClosure3'
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.commons.services.CommonService$AjcClosure5'
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.subproject.services.Repository$AjcClosure1'
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.commons.model.dao.BaseDAO$AjcClosure1'
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.commons.model.dao.BaseDAO$AjcClosure3'
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.commons.model.dao.BaseDAO$AjcClosure5'
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.commons.model.dao.BaseDAO$AjcClosure7'
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.subproject.model.dao.LastDocumentNumberDAO$AjcClosure1'
 ...

But when booting the EAR with this war inside, BaseDAO class is ignored completely:

 ...
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.commons.services.CommonService$AjcClosure1'
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.commons.services.CommonService$AjcClosure3'
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.commons.services.CommonService$AjcClosure5'
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.subproject.services.Repository$AjcClosure1'
 ServerService Thread Pool -- 227 ? [ModuleClassLoader@1b3a9e75] debug generating class 'com.myproject.subproject.model.dao.LastDocumentNumberDAO$AjcClosure1'
 ...

Solution

  • Finally we found where the problem was. It was in the jboss-deployment-structure.xml. Every war in the project had its own jboss-deployment-structure.xml with some exclusions:

    <jboss-deployment-structure>
      <deployment>
        <!-- Exclusions allow you to prevent the server from automatically adding some dependencies -->
        <exclusions>
          <module name="org.apache.log4j" />
          <module name="org.slf4j" />
          <module name="org.apache.commons.logging" />
          <module name="org.log4j" />
          <module name="org.jboss.logging" />
          <module name="org.javassist" />
          <module name="org.hibernate.validator" />
          <module name="org.jboss.ws.cxf" />
        </exclusions>
        <exclude-subsystems>
          <subsystem name="webservices" />
        </exclude-subsystems>
      </deployment>
    </jboss-deployment-structure>
    

    But in the EAR deployment the EAR's specific jboss-deployment-structure.xml was missing so the classloader was working in a very diferent way, creating the issues that i post in my question. Simply putting the jboss-deployment-structure.xml (the EAR one, that is a combination of the WAR ones) in the EAR's META-INF solved the problem.

    Hope this helps someone with similar problems.