]
Frigo Coder edited comment on CDI-552 at 10/11/18 9:12 AM:
-----------------------------------------------------------
This is a very desired feature that would be useful in several scenarios:
- Migrating legacy code
- Weld SE applications
- Rich domain objects
- OOP applications with advanced features
A proxy based solution would be preferable to maintain consistency with CDI, however this
would interfere with direct field access. Runtime weaving solutions are also possible with
AspectJ, JavaAgent, or ClassLoader hacks. The new keyword would be optimal, but helper
functions or classes are also acceptable.
I have a toy implementation that only approximates the real thing with severe limitations
obviously:
{code:java}
public class Manual<T> implements AutoCloseable {
/**
* Does not support constructor interceptors
*/
public static <T> Manual<T> from(T instance) {
return new Manual<>(instance);
}
/**
* Does not support constructor parameters
*/
public static <T> Manual<T> create(Class<T> clazz) {
return new Manual<>(clazz);
}
private BeanManager bm;
private CreationalContext<T> ctx;
private InjectionTargetFactory<T> itf;
private InjectionTarget<T> it;
private InterceptionFactory<T> ifm;
private T instance;
private T proxy;
@SuppressWarnings("unchecked")
private Manual(T instance) {
prepare((Class<T>) instance.getClass());
process(instance);
}
private Manual(Class<T> clazz) {
prepare(clazz);
process(it.produce(ctx));
}
private void prepare(Class<T> clazz) {
bm = CDI.current().getBeanManager();
ctx = bm.createCreationalContext(null);
itf = bm.getInjectionTargetFactory(bm.createAnnotatedType(clazz));
// itf.configure(); // this fucks up things
it = itf.createInjectionTarget(null);
ifm = bm.createInterceptionFactory(ctx, clazz);
ifm.configure();
}
private void process(T object) {
this.instance = object;
it.inject(instance, ctx);
it.postConstruct(instance);
proxy = ifm.createInterceptedInstance(instance);
}
@Override
public void close() {
it.preDestroy(instance);
it.dispose(instance);
ctx.release();
}
@Override
protected void finalize() throws Throwable {
it.preDestroy(instance);
it.dispose(instance);
ctx.release();
super.finalize();
}
/**
* Neither of them supports direct field access due to proxy
*/
public T get() {
return proxy;
}
}
{code}
was (Author: frigocoder):
This is a very desired feature that would be useful in several scenarios:
- Migrating legacy code
- Weld SE applications
- Rich domain objects
- OOP applications with advanced features
A proxy based solution would be preferable to maintain consistency with CDI, however this
would interfere with direct field access. Runtime weaving solutions are also possible with
AspectJ, JavaAgent, or ClassLoader hacks. The new keyword would be optimal, but helper
functions or classes are also acceptable.
I have a toy implementation that only approximates the real thing with severe limitations
obviously:
{{public class Manual<T> implements AutoCloseable {
/**
* Does not support constructor interceptors
*/
public static <T> Manual<T> from(T instance) {
return new Manual<>(instance);
}
/**
* Does not support constructor parameters
*/
public static <T> Manual<T> create(Class<T> clazz) {
return new Manual<>(clazz);
}
private BeanManager bm;
private CreationalContext<T> ctx;
private InjectionTargetFactory<T> itf;
private InjectionTarget<T> it;
private InterceptionFactory<T> ifm;
private T instance;
private T proxy;
@SuppressWarnings("unchecked")
private Manual(T instance) {
prepare((Class<T>) instance.getClass());
process(instance);
}
private Manual(Class<T> clazz) {
prepare(clazz);
process(it.produce(ctx));
}
private void prepare(Class<T> clazz) {
bm = CDI.current().getBeanManager();
ctx = bm.createCreationalContext(null);
itf = bm.getInjectionTargetFactory(bm.createAnnotatedType(clazz));
// itf.configure(); // this fucks up things
it = itf.createInjectionTarget(null);
ifm = bm.createInterceptionFactory(ctx, clazz);
ifm.configure();
}
private void process(T object) {
this.instance = object;
it.inject(instance, ctx);
it.postConstruct(instance);
proxy = ifm.createInterceptedInstance(instance);
}
@Override
public void close() {
it.preDestroy(instance);
it.dispose(instance);
ctx.release();
}
@Override
protected void finalize() throws Throwable {
it.preDestroy(instance);
it.dispose(instance);
ctx.release();
super.finalize();
}
/**
* Neither of them supports direct field access due to proxy
*/
public T get() {
return proxy;
}
}
}}
Add support for injection, decorators and interceptors on
"new-ed" objects
--------------------------------------------------------------------------
Key: CDI-552
URL:
https://issues.jboss.org/browse/CDI-552
Project: CDI Specification Issues
Issue Type: Feature Request
Components: Beans, Decorators, Interceptors, Resolution
Affects Versions: 2.0-EDR1
Reporter: Rogerio Liesenfeld
Priority: Major
The current CDI programming model is not friendly to object-oriented code or proper class
design, and does not support true POJOs.
With this I mean:
1) For object-oriented code, I need to be able to instantiate and use *stateful*,
short-lived, objects, while still having @Inject fields in it. I shouldn't be forced
to have a stateless (non-OO) class (ie, a [Transaction
Script|http://martinfowler.com/eaaCatalog/transactionScript.html]).
2) Most classes in a business app are not meant to be used as subclasses, ie, they are
not designed for extension; therefore, I should be able to make them {{final}} (see
http://lcsd05.cs.tamu.edu/slides/keynote.pdf, page 26, or item 17 in the
[
book|http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683]).
3) For a class to truly be a POJO, I must be able to make *full use* of the Java language
when designing and implementing it; arbitrary constraints like "can't be
final", "can't have final instance fields", "cannot be
instantiated directly", etc. prevent it from being a "plain-old" Java
object.
Specifically, what I want is to be able to write the following in a JSF/CDI backing bean
for a web UI:
{code}
MyBusinessService businessOp = new MyBusinessService(fieldFromUI1, fieldFromUI2,
listWithMoreDataFromUI);
businessOp.performSomeBusinessOperation(otherArgs);
String result1 = businessOp.getResultXyz();
List<result> moreResultData = businessOp.getFinalData();
{code}
... while having MyBusinessService be a CDI bean containing one or more
@Inject/@PersistenceContext fields (typically, an EntityManager and perhaps other service
beans).
Without this ability, application developers are forced to create procedural Transation
Scripts (stateless service class, which tend to have low cohesion).
For a CDI implementation to do this, it will need to use the java.lang.instrument API,
like others tools (AspectJ, JBoss AOP, JBoss Byteman, JaCoCo, JMockit) already do.
Also, for reference, the Spring framework already supports it for some time:
http://docs.spring.io/spring/docs/3.0.0.M3/spring-framework-reference/htm...