0
votes

Using Weld 1.1.13.Final in test with Arquillian....

Let's say I inject into a field something volatile. Something like a property subject to change that I want the bean owning the injection point to receive change events. Thought about creating a CDI extension.

Caught ProcessAnnotatedType event and looking for all fields that have an custom annotation on field injection points:

 <T> void pat(@Observes ProcessAnnotatedType<T> event, BeanManager bm) {
   final AnnotatedType<T> target = event.getAnnotatedType();

   for (AnnotatedField<? super T> field : target.getFields())
     if (field.isAnnotationPresent(Value.class)) {  // ignore that I don't check @Inject here for the moment
        CtClass wrapper = pool.get(target.getJavaClass().getName());
        ConstPool cp = wrapper.getClassFile().getConstPool();

        CtMethod m = CtNewMethod.make(....)
        ....
        wrapper.addMethod(m);

        event.setAnnotatedType(bm.createAnnotatedType(wrapper.toClass()));
     }
 }

Had even grabbed thereafter all the injection points for fields and replaced the underlying WeldField with a new Field corresponding the "wrapper" type. Otherwise bean validation fails.

But this only works for stuff setup during startup not when for example Arquillian uses the Bean Manager to initialize a class that injects one of my "wraps". Things fail since the Bean Resolver uses the Type as a hash key to find beans.

Basically I don't think I can "mask" a class that is annotated (made into a bean) by the CDI with an extra method to receive custom events. Would have been cool but a Type is a Type (i.e. no idea how to proxy or fake the equals/hashCode).

1
Your question is a bit hard to understand. CDI objects are injected at runtime and are scoped within certain bounds. Dependent scoped beans are always created newly when injected, application scoped are cached for the lifetime of the application. Maybe if you clarified some of your question it would help understand what you're trying to do. - John Ament
Only thing I can think of now is to keep a weak reference to beans (somehow monitor calls against the BeanManager interface to be portable) and do reflection on the fields. - Matthew Campbell
No progress here. Another way might be to drill down the annotated types searching for fields to switch out with my proxied type. - Matthew Campbell
I think you may be over complicating the problem. Let's say you have a POJO that contains some amount of request data. Why not just inject this POJO wherever you want this volatile data? - John Ament
@John, Not sure I understand your suggestion. My question is about trying to modify types prior to them being wired by the CDI so that I can catch events after a bean has been registered. - Matthew Campbell

1 Answers

0
votes

Got it. Turns out the compute value function (google extension) inside the TypeSafeBeanResolver resolver (at least the CDI Weld implementation) is smart. If I just extend the class:

 CtClass wrapper = pool.makeClass(target.getJavaClass().getName()+"Proxy");
 wrapper.setSuperclass(pool.get(target.getJavaClass().getName()));
 .....
 final AnnotatedType<T> other = bm.createAnnotatedType(wrapper
                    .toClass());

then everything works fine. Tested capturing an event in a bean. Will post the code on a Gist with a comment.