Announcement Announcement Module
Collapse
No announcement yet.
Apache CXF, AOP, and dependency injection Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Apache CXF, AOP, and dependency injection

    Hello,

    Not sure if this is the place to post this, here is my problem:

    1. I have the following architecture (Apache CXF for webservices, service layer, spring roo, db)
    2. I created a simple LoggingAspect and specified the following execution:
    @Around("execution(* com.company.pkg.services.impl.*.*(..))")

    Here are my problems:
    1. One of my service methods has the following signature Long getSomething(), my other methods are void. With the LoggingAspect enabled and CXF present, void methods work, but the method returning a Long throws an exception. If I remove the LoggingAspect all methods work.
    2. For some reason the Autowired injected objects are null on services annotated with CXF @WebService tags.

    Has anyone seen anything similar or have any idea what maybe happening. I am baffled why the injected objects are null.

    FYI. I placed a breakpoint in the constructor of the service and on spring initialization the service gets initialized 3 times, while the injected object setter gets called once.

  • #2
    How does your around advice body look? I suspect that you may not be returning a right kind of object from it (typically you should have something to effect of "return pjp.proceed()").

    A bit more code might be helpful to resolve the other issue.

    -Ramnivas

    Comment


    • #3
      Originally posted by ramnivas View Post
      How does your around advice body look? I suspect that you may not be returning a right kind of object from it (typically you should have something to effect of "return pjp.proceed()").

      A bit more code might be helpful to resolve the other issue.

      -Ramnivas
      Ramnivas,

      Here is the aspect code, I'll provide additional info on the second point tomorrow.

      package project.pkg.framework.spring;

      import org.apache.commons.logging.Log;
      import org.apache.commons.logging.LogFactory;
      import org.aspectj.lang.ProceedingJoinPoint;
      import org.aspectj.lang.annotation.Around;
      import org.aspectj.lang.annotation.Aspect;

      @Aspect
      public class LoggingAspect
      {
      private static Log log = null;

      @Around("execution(* project.pkg.service.TemplateService*.*(..))")
      public Object log(ProceedingJoinPoint call) throws Throwable
      {
      log = LogFactory.getLog(call.getClass());
      log.info("from logging aspect: entering method [" +call.toShortString()+"] with param:"+call.getArgs()[0]);
      Object point = call.proceed();
      log.info("from logging aspect: exiting method [" + call.toShortString() + "with return as:" +point);
      return point;
      }

      }

      Comment


      • #4
        Could it be that your method takes zero argument and you are using getArgs()[0] leading to an ArrayIndexOutOfBoundsException?

        -Ramnivas

        Comment


        • #5
          Originally posted by ramnivas View Post
          Could it be that your method takes zero argument and you are using getArgs()[0] leading to an ArrayIndexOutOfBoundsException?

          -Ramnivas
          Ramnivas,

          Great catch, its one of those I've been staring at the code for too long Thanks !

          Regarding the second issues here is some code, its pretty much boiler plate but here goes, nothing fancy.

          1. EmailServiceImpl
          package services.impl;

          import javax.jws.WebService;

          import org.springframework.beans.factory.annotation.Autow ired;
          import org.springframework.stereotype.Service;

          import framework.ServiceContext;
          import services.EmailService;
          import services.exception.ServicesException;


          @Service
          @WebService(endpointInterface = "services.EmailService")
          public class EmailServiceImpl implements EmailService {

          @Autowired
          private transient org.springframework.mail.MailSender mailTemplate;

          @Override
          public void sendMessage(ServiceContext context, String mailFrom, String subject, String mailTo, String message)
          throws ServicesException
          {
          org.springframework.mail.SimpleMailMessage simpleMailMessage = new org.springframework.mail.SimpleMailMessage();
          simpleMailMessage.setFrom(mailFrom);
          simpleMailMessage.setSubject(subject);
          simpleMailMessage.setTo(mailTo);
          simpleMailMessage.setText(message);
          mailTemplate.send(simpleMailMessage);
          }
          }

          2. applicationContext.xml (generated by Roo)
          <?xml version="1.0" encoding="UTF-8" standalone="no"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:aop="http://www.springframework.org/schema/aop"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:cxf="http://cxf.apache.org/core"
          xmlns:jaxws="http://cxf.apache.org/jaxws"
          xmlns:jee="http://www.springframework.org/schema/jee"
          xmlns:tx="http://www.springframework.org/schema/tx"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:task="http://www.springframework.org/schema/task"
          xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schem...ng-jee-3.0.xsd
          http://www.springframework.org/schema/aop http://www.springframework.org/schem...ng-aop-3.0.xsd
          http://www.springframework.org/schema/task http://www.springframework.org/schem...g-task-3.0.xsd
          http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
          http://www.springframework.org/schema/beans http://www.springframework.org/schem...-beans-3.0.xsd
          http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
          http://www.springframework.org/schema/tx http://www.springframework.org/schem...ing-tx-3.0.xsd
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">


          <import resource="classpath:META-INF/cxf/cxf.xml"/>
          <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
          <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>

          <!-- Enable message logging using the CXF logging feature -->
          <cxf:bus>
          <cxf:features>
          <cxf:logging/>
          </cxf:features>
          </cxf:bus>

          <!--
          This will automatically locate any and all property files you have
          within your classpath, provided they fall under the META-INF/spring
          directory. The located property files are parsed and their values can
          then be used within application context files in the form of
          ${propertyKey}.
          -->
          <contextroperty-placeholder location="classpath*:META-INF/spring/*.properties"/>

          <!--
          Turn on AspectJ @Configurable support. As a result, any time you
          instantiate an object, Spring will attempt to perform dependency
          injection on that object. This occurs for instantiation via the "new"
          keyword, as well as via reflection. This is possible because AspectJ
          is used to "weave" Roo-based applications at compile time. In effect
          this feature allows dependency injection of any object at all in your
          system, which is a very useful feature (without @Configurable you'd
          only be able to dependency inject objects acquired from Spring or
          subsequently presented to a specific Spring dependency injection
          method). Roo applications use this useful feature in a number of
          areas, such as @PersistenceContext injection into entities.
          -->
          <context:spring-configured/>

          <!--
          This declaration will cause Spring to locate every @Component,
          @Repository and @Service in your application. In practical terms this
          allows you to write a POJO and then simply annotate the new POJO as an
          @Service and Spring will automatically detect, instantiate and
          dependency inject your service at startup time. Importantly, you can
          then also have your new service injected into any other class that
          requires it simply by declaring a field for your service inside the
          relying class and Spring will inject it. Note that two exclude filters
          are declared. The first ensures that Spring doesn't spend time
          introspecting Roo-specific ITD aspects. The second ensures Roo doesn't
          instantiate your @Controller classes, as these should be instantiated
          by a web tier application context. Refer to web.xml for more details
          about the web tier application context setup services.

          Furthermore, this turns on @Autowired, @PostConstruct etc support. These
          annotations allow you to use common Spring and Java Enterprise Edition
          annotations in your classes without needing to do any special configuration.
          The most commonly used annotation is @Autowired, which instructs Spring to
          dependency inject an object into your class.
          -->
          <context:component-scan base-package="com.fox.dv">
          <context:exclude-filter expression=".*_Roo_.*" type="regex"/>
          <context:exclude-filter expression="org.springframework.stereotype.Control ler" type="annotation"/>
          </context:component-scan>

          <bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
          <property name="driverClassName" value="${database.driverClassName}"/>
          <property name="url" value="${database.url}"/>
          <property name="username" value="${database.username}"/>
          <property name="password" value="${database.password}"/>
          </bean>
          <bean class="org.springframework.orm.jpa.JpaTransactionM anager" id="transactionManager">
          <property name="entityManagerFactory" ref="entityManagerFactory"/>
          </bean>
          <tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
          <bean class="org.springframework.orm.jpa.LocalContainerE ntityManagerFactoryBean" id="entityManagerFactory">
          <property name="dataSource" ref="dataSource"/>
          </bean>


          <!-- CXF Web Services end points -->
          <jaxws:endpoint address="/Email" id="email" implementor="services.impl.EmailServiceImpl"/>

          <!-- Email Service setup -->
          <bean class="org.springframework.mail.javamail.JavaMailS enderImpl" id="mailSender">
          <property name="host" value="${email.host}"/>
          </bean>


          </beans>

          Comment


          • #6
            Originally posted by ramnivas View Post
            Could it be that your method takes zero argument and you are using getArgs()[0] leading to an ArrayIndexOutOfBoundsException?

            -Ramnivas
            Ramnivas, thanks !! that was it. I submitted additional info on item 2, but waiting for approval. Second pair of eyes always helps.

            Comment

            Working...
            X