Re: [aspectj-users] Anyway to use AJ to _prevent_ field assignment at initialization of an object?

2019-08-09 Thread Alexander Kriegisch
I just wanted to show how to use an around advice on field write access. Actually in your case it is simpler. Assuming the bogus constructor looks like this in my previous code:
public DefaultCacheResolverFactory() {  System.out.println("DefaultCacheResolverFactory: no-args constructor");  throw new RuntimeException("oops!");}
You can just change the aspect to:
package de.scrum_master.aspect;import de.scrum_master.app.CacheManager;import de.scrum_master.app.DefaultCacheResolverFactory;public aspect CacheResolverFactoryReplacer {  DefaultCacheResolverFactory around() : call(DefaultCacheResolverFactory.new()) {return new DefaultCacheResolverFactory(new CacheManager("aspect"));  }}
-- Alexander Kriegischhttps://scrum-master.de
Eric B schrieb am 09.08.2019 19:42:


Thanks for the great example Alexander.
 
But to make you SSCCE example more inline with what is happening, the no-arg constructor for DefaultCacheResolverFactory should be throwing a runtime exception.
 
Consequently, just using a set() alone will still throw the exception since the no-arg cstor is still being called.
 
I can wrap the set() with a cflow() as you suggested and catch the exception, but in an ideal world, I would rather prevent the call to the no-arg cstor altogether.
 
So essentially, I would be looking at doing something like:
 
Around(cflow(initialization(CacheLookupUtil.new(..)) && call(DefaultCacheResolverFactory.new())){
   return new DefaultCacheResolverFactory( new CacheManager();
}I haven't tried that yet, but I believe it should get me where I need to get.  
 
Thanks,
 
Eric
 


On Thu, Aug 8, 2019, 9:48 PM Alexander Kriegisch 

Re: [aspectj-users] Anyway to use AJ to _prevent_ field assignment at initialization of an object?

2019-08-09 Thread Eric B
Thanks for the great example Alexander.

But to make you SSCCE example more inline with what is happening, the
no-arg constructor for DefaultCacheResolverFactory should be throwing a
runtime exception.

Consequently, just using a set() alone will still throw the exception since
the no-arg cstor is still being called.

I can wrap the set() with a cflow() as you suggested and catch the
exception, but in an ideal world, I would rather prevent the call to the
no-arg cstor altogether.

So essentially, I would be looking at doing something like:

Around(cflow(initialization(CacheLookupUtil.new(..)) &&
call(DefaultCacheResolverFactory.new())){
   return new DefaultCacheResolverFactory( new CacheManager();
}


I haven't tried that yet, but I believe it should get me where I need to
get.

Thanks,

Eric


On Thu, Aug 8, 2019, 9:48 PM Alexander Kriegisch  I replicated your situation with dummy classes:
> --
>
> package de.scrum_master.app;
>
> public class InvocationContext {}
>
> --
>
> package de.scrum_master.app;
>
> public interface CacheResolverFactory {
>   CacheManager getCacheManager();
> }
>
> --
>
> package de.scrum_master.app;
>
> public class DefaultCacheResolverFactory implements CacheResolverFactory {
>   private CacheManager cacheManager = new CacheManager("default");
>   public DefaultCacheResolverFactory() {
> System.out.println("DefaultCacheResolverFactory: no-args constructor");
>   }
>
>   public DefaultCacheResolverFactory(CacheManager cacheManager) {
> System.out.println("DefaultCacheResolverFactory: constructor with 
> CacheManager");
> this.cacheManager = cacheManager;
>   }
>
>   @Override
>   public CacheManager getCacheManager() {
> return cacheManager;
>   }
> }
>
> --
>
> package de.scrum_master.app;
>
> public class CacheManager {
>   private String name;
>
>   public CacheManager(String name) {
> this.name = name;
>   }
>
>   @Override
>   public String toString() {
> return "CacheManager [name=" + name + "]";
>   }
> }
>
> --
>
> package de.scrum_master.app;
>
> public abstract class AbstractCacheLookupUtil {
>   public abstract void doSomething();
> }
>
> --
>
> package de.scrum_master.app;
>
> public class CacheLookupUtil extends 
> AbstractCacheLookupUtil {
>   private CacheResolverFactory defaultCacheResolverFactory = new 
> DefaultCacheResolverFactory();
>
>   @Override
>   public void doSomething() {
> System.out.println(defaultCacheResolverFactory.getCacheManager());
>   }
>
>   public static void main(String[] args) {
> new CacheLookupUtil().doSomething();
>   }
> }
>
> --
>
> Now if you run that code, the console log says:
>
> DefaultCacheResolverFactory: no-args constructor
> CacheManager [name=default]
>
> No surprise here.
>
> Now you can use LTW (load-time weaving) and a set() pointcut like this:
> --
>
> package de.scrum_master.aspect;
>
> import de.scrum_master.app.CacheResolverFactory;
> import de.scrum_master.app.DefaultCacheResolverFactory;
> import de.scrum_master.app.CacheLookupUtil;
> import de.scrum_master.app.CacheManager;
>
> public aspect CacheResolverFactoryReplacer {
>   void around(CacheResolverFactory cacheResolverFactory) :
> set(CacheResolverFactory CacheLookupUtil.*) &&
> args(cacheResolverFactory)
>   {
> proceed(new DefaultCacheResolverFactory(new CacheManager("aspect")));
>   }
> }
>
> --
>
> The console log changes to:
>
> DefaultCacheResolverFactory: no-args constructor
> DefaultCacheResolverFactory: constructor with CacheManager
> CacheManager [name=aspect]
>
> Now as you can see, the no-args resolver factory constructor is still
> executed but the resulting object is no longer assigned to the member
> because the advice proceeds with the object you want to be assigned instead.
>
> If you want to be very specific in your aspect and limit setting the
> member during constructor execution or object initialisation, you can
> always add && cflow(execution(CacheLookupUtil.new(..))) or &&
> cflow(initialization(CacheLookupUtil.new(..))) to your pointcut.
> --
> Alexander Kriegisch
> https://scrum-master.de
>
>
>
> Eric B schrieb am 08.08.2019 21:20:
>
> I'm using the JCache API, in which a design decision made by the JSR-107
> team in implementing the Reference Implementation is causing me a
> significant headache.  The class in question is:
> org.jsr107.ri.annotations.cdi.CacheLookupUtil from package org.jsr107.ri:
> cache-annotations-ri-cdi:1.1.0.
>
> This is the layout of the class:
>
>
> public class CacheLookupUtil extends 
> AbstractCacheLookupUtil {
>   @Inject
>   private BeanManagerUtil beanManagerUtil;
>
>   private CacheKeyGenerator defaultCacheKeyGenerator = new 
> DefaultCacheKeyGenerator();
>   private CacheResolverFactory defaultCacheResolverFactory