[
https://issues.apache.org/jira/browse/FELIX-4614?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14112203#comment-14112203
]
Pierre De Rop commented on FELIX-4614:
--------------------------------------
In order to make sure I understand, can we discuss about the following example:
for instance, assume that you want to create an aspect service as a java
DynamicProxy.
To do so, you can use a Factory object instance with a create method, and that
Factory has to hold the necessary informations in order to create the dynamic
proxy (at least we need the aspect interface class, but the Factory could hold
more data, if necessary, like a label in the following example):
{code}
public class Activator extends DependencyActivatorBase {
public static interface ServiceInterface {
public void invoke();
}
public static class ServiceProvider implements ServiceInterface {
public void invoke() {
System.out.println("ServiceProvider.invoke");
}
}
public static class ServiceConsumer {
volatile ServiceInterface m_service;
public void start() {
System.out.println("ServiceConsumer.start");
m_service.invoke();
}
}
static class AspectProxy implements InvocationHandler {
private volatile ServiceInterface m_service;
private final String m_label;
public AspectProxy(String label) {
m_label = label;
}
public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
System.out.println("AspectProxy.invoke (label=" + m_label + ")");
Method m = m_service.getClass().getMethod(method.getName(),
method.getParameterTypes());
return m.invoke(m_service, args);
}
}
public static class AspectProxyFactory {
private Class m_class;
private final String m_label;
public AspectProxyFactory(Class clazz, String label) {
m_class = clazz;
m_label = label;
}
public Object create() {
return Proxy.newProxyInstance(m_class.getClassLoader(), new Class[]
{ m_class }, new AspectProxy(m_label));
}
}
@Override
public void init(BundleContext context, DependencyManager mgr) throws
Exception {
mgr.add(createComponent()
.setInterface(ServiceInterface.class.getName(), null)
.setImplementation(ServiceProvider.class));
mgr.add(createAspectService(ServiceInterface.class, null, 10,
"m_service")
.setFactory(new AspectProxyFactory(ServiceInterface.class, "label"),
"create"));
mgr.add(createComponent()
.setImplementation(ServiceConsumer.class)
.add(createServiceDependency().setService(ServiceInterface.class).setRequired(true)));
}
}
{code}
so, in the above example, the AspectProxyFactory class holds the
ServiceInterface class in its "m_class" attribute (needed to create the
DynamicProxy), as well as a "m_label" field, which will be passed to the
DynamicProxy constructor.
So, can you please modify the example above in order to let me understand what
kind of improvement you would like to have ?
Do you mean that the org.apache.felix.dm.Component object (for the aspect)
should be passed to the create method and then the Factory could do a
class.forName on the aspect interface (that can be accessed from
Component.getComponentDeclaration().getServices() method in dependency manager
4.0.0, from the sanbdox) in order to be able to create the java DynamicProxy ?
But yet, we still have to hold the "label" context in the Factory object, in
order to pass it to the AspectProxy constructor ...
So, it is not exaclty what may be you would like to have, but I wonder about
the following improvement: instead of having a setFactory(Object
factoryInstance method, String create method), we could then introduce a simple
interface in DM API that would only have a create method, and notice that
having one single method would allow to use a nice lambda in java8, since it
would be compatible with a functional interface:
Something like
{code}
package org.apache.felix.dm;
// @FunctionalInterface
public interface Factory {
Object create();
}
{code}
then we could introduce a new setFactory(Factory factory) method in the
Component interface:
{code}
interface Component {
...
void setFactory(Factory factory);
}
{code}
and given the initial example, we could then do something like this (in java8
style):
{code}
mgr.add(createAspectService(ServiceInterface.class, null, 10,
"m_service")
.setFactory(() ->
new
Proxy.newProxyInstance(ServiceInterface.class.getClassLoader(),
new Class[]
{ServiceInterface.class }, new AspectProxy("label"));
);
{code}
and in java7:
{code}
mgr.add(createAspectService(ServiceInterface.class, null, 10,
"m_service")
.setFactory(new Factory() {
public Object create() {
return new
Proxy.newProxyInstance(ServiceInterface.class.getClassLoader(),
new Class[] {ServiceInterface.class }, new AspectProxy("label"));
}
}));
{code}
(not sure if this is making sense or if this is really what you would like to
have, please let me know what you think ...)
/pierre
> Factory create() method should have access to the component definition
> ----------------------------------------------------------------------
>
> Key: FELIX-4614
> URL: https://issues.apache.org/jira/browse/FELIX-4614
> Project: Felix
> Issue Type: Improvement
> Components: Dependency Manager
> Reporter: Paul Bakker
>
> Currently the factory mechanism uses a _create()_ method without arguments.
> Because of this there is not enough context to create instances. For example
> creating a Proxy is not possible because we don't know which interface to use
> for the Proxy.
> The _create()_ method should support an argument to get access to the
> component definition.
--
This message was sent by Atlassian JIRA
(v6.2#6252)