Announcement Announcement Module
Collapse
No announcement yet.
Introduction on domain objects on business method? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Introduction on domain objects on business method?

    I need to introduce new methods on domain objects passed to business methods.

    If yes how could I do this on the following sample? I am specifically looking for the joinpoint

    Code:
    @Aspect
    public class UsageTracking {
    
      @DeclareParents(value="com.xzy.myapp.domain.*+",
                      defaultImpl=DefaultUsageTracked.class)
      public static UsageTracked mixin;
      
      @Before("com.xyz.myapp.SystemArchitecture.businessService() && <I NEED SOMETHING HERE>")
      public void recordUsage(UsageTracked usageTracked) {
        usageTracked.incrementUseCount();
        
       //IS THERE ANY CLEAN WHY TO GET ACCESS OF TARGET OBJECT? 
      // DomainObject do = (DomainObject) usageTracked;
      }
      
    }

  • #2
    Originally posted by SpringingSpringles View Post
    I need to introduce new methods on domain objects passed to business methods.

    If yes how could I do this on the following sample? I am specifically looking for the joinpoint

    Code:
    @Aspect
    public class UsageTracking {
    
      @DeclareParents(value="com.xzy.myapp.domain.*+",
                      defaultImpl=DefaultUsageTracked.class)
      public static UsageTracked mixin;
      
      @Before("com.xyz.myapp.SystemArchitecture.businessService() && <I NEED SOMETHING HERE>")
      public void recordUsage(UsageTracked usageTracked) {
        usageTracked.incrementUseCount();
        
       //IS THERE ANY CLEAN WHY TO GET ACCESS OF TARGET OBJECT? 
      // DomainObject do = (DomainObject) usageTracked;
      }
      
    }
    You can't introduce new methods on domain objects with Spring AOP. If you want to advise domain objects you have to use AspectJ and weave in your new methods, can't be done with Spring AOP.

    Comment


    • #3
      Originally posted by bdangubic View Post
      You can't introduce new methods on domain objects with Spring AOP. If you want to advise domain objects you have to use AspectJ and weave in your new methods, can't be done with Spring AOP.
      Thank you for answer. Can you point to some example with aspectj on this please?

      Comment


      • #4
        Originally posted by SpringingSpringles View Post
        Thank you for answer. Can you point to some example with aspectj on this please?
        I got it with aspectj and spring. Here is the code for anyone interested.

        DOMAIN OBJECTS:
        Code:
        package com.sample.domain;
        
        public class Sample {
        
        	private Long id;
        	private String type;
        	private String description;
        
        	public String getType() {
        		return type;
        	}
        
        	public void setType(String type) {
        		this.type = type;
        	}
        
        	public String getDescription() {
        		return description;
        	}
        
        	public void setDescription(String description) {
        		this.description = description;
        	}
        
        	public Long getId() {
        		return id;
        	}
        
        	public void setId(Long id) {
        		this.id = id;
        	}
        
        }
        SERVICES:

        Code:
        package com.sample.service;
        
        import java.util.List;
        
        import com.sample.domain.Sample;
        
        
        public interface SampleService {
        
        	public Sample saveSample(Sample sample);
        
        	public Sample addSample(Sample sample);
        
        	public Sample getRandomSample();
        
        	public List<Sample> saveSamples(List<Sample> samples);
        
        	public List<Sample> getRandomSamples();
        }
        Code:
        package com.sample.service.impl;
        
        import java.util.ArrayList;
        import java.util.HashMap;
        import java.util.List;
        
        import org.apache.commons.lang.RandomStringUtils;
        import org.apache.commons.logging.Log;
        import org.apache.commons.logging.LogFactory;
        import org.springframework.stereotype.Service;
        
        import com.sample.domain.Sample;
        import com.sample.service.SampleService;
        
        @Service
        public class SampleServiceImpl implements SampleService {
        
        	private static Log log = LogFactory.getLog(SampleServiceImpl.class);
        
        	private HashMap<Long, Sample> store = new HashMap<Long, Sample>();
        
        	protected Sample saveToStore(Sample sample) {
        		if (store.containsKey(sample.getId())) {
        			store.put(sample.getId(), sample);
        			log.info("Sample " + sample.getId() + " saved!");
        		} else {
        			log.warn("Sample " + sample.getId() + " not found in store!");
        		}
        		return sample;
        	}
        
        	protected Sample getSample(Long id) {
        		return store.get(id);
        	}
        
        	protected Sample getOrGenerateSample() {
        		long id = (long) (Math.random() * 100);
        		Sample sample = getSample(id);
        		if (sample == null) {
        			sample = new Sample();
        			sample.setId(id);
        			sample.setType(RandomStringUtils.randomAlphanumeric((int) id));
        			sample.setDescription(RandomStringUtils.randomAlphabetic((int) id));
        			store.put(id, sample);
        		}
        		return sample;
        	}
        
        	public Sample addSample(Sample sample) {
        		log.info("target: " + sample.getClass());
        		return saveToStore(sample);
        	}
        
        	public Sample getRandomSample() {
        		return getOrGenerateSample();
        	}
        
        	public List<Sample> getRandomSamples() {
        		int count = (int) (Math.random() * 20);
        		if (count == 0) {
        			count++;
        		}
        		;
        		ArrayList<Sample> samples = new ArrayList<Sample>(count);
        		for (int i = 0; i < count; i++) {
        			samples.add(getOrGenerateSample());
        		}
        		return samples;
        	}
        
        	public Sample saveSample(Sample sample) {
        		log.info("target: " + sample.getClass());
        		return saveToStore(sample);
        	}
        
        	public List<Sample> saveSamples(List<Sample> samples) {
        		for (Sample sample : samples) {
        			saveToStore(sample);
        		}
        		return samples;
        	}
        
        }
        ASPECTS:
        Code:
        package com.sample.aspect;
        
        public interface UsageTracked {
        
        	public void incrementUseCount();
        
        	public long getUseCount();
        }
        Code:
        package com.sample.aspect;
        
        
        public class DefaultUsageTracked implements UsageTracked {
        
        	private long useCount = 0;
        
        	public long getUseCount() {
        		return useCount;
        	}
        
        	public void incrementUseCount() {
        		useCount++;
        	}
        
        }
        Code:
        package com.sample.aspect;
        
        import org.apache.commons.logging.Log;
        import org.apache.commons.logging.LogFactory;
        import org.aspectj.lang.annotation.Aspect;
        import org.aspectj.lang.annotation.Before;
        import org.aspectj.lang.annotation.DeclareParents;
        
        import com.sample.domain.Sample;
        
        @Aspect
        public class UsageTrackingIntroduction {
        
        	private Log log = LogFactory.getLog(UsageTrackingIntroduction.class);
        
        	@DeclareParents(value = "com.sample.domain.*", defaultImpl = DefaultUsageTracked.class)
        	private static UsageTracked usageTracked;
        
        	@Before("execution(public * com.sample.service.SampleService.*(..)) && args(usageTracked)")
        	public void recordUsage(UsageTracked usageTracked) {
        		usageTracked.incrementUseCount();
        		log.info("Use count: " + usageTracked.getUseCount());
        		log.info("target: " + usageTracked.getClass());
        		if (usageTracked instanceof Sample) {
        			Sample sample = (Sample) usageTracked;
        			log.info("Hooray!");
        		}
        	}
        }
        MAIN :
        Code:
        package com.sample;
        
        
        import org.springframework.context.ApplicationContext;
        import org.springframework.context.support.ClassPathXmlApplicationContext;
        
        import com.sample.domain.Sample;
        import com.sample.service.SampleService;
        
        
        public class AopTestsMain {
        
        	public static void main(String[] args) {
        		ApplicationContext ctx = new ClassPathXmlApplicationContext(
        				"AopTests-context.xml");
        		SampleService sampleService = (SampleService) ctx
        				.getBean("sampleServiceImpl");
        		Sample sample = sampleService.getRandomSample();
        		sample.setDescription("I am new");
        		sample.setType("unique?");
        
        		sampleService.saveSample(sample);
        	}
        }
        META-INF/aop.xml
        Code:
        <!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.sample.domain.*" />
        		<include within="com.sample.aspect.*" />
        		<include within="com.sample.service.impl.*" />
        	</weaver>
        
        	<aspects>
        		<!-- weave in just this aspect -->
        		<!-- <aspect name="com.sample.ProfilingAspect" /> -->
        		<aspect name="com.sample.aspect.UsageTrackingIntroduction" />
        	</aspects>
        
        </aspectj>

        Comment

        Working...
        X