[
https://issues.apache.org/jira/browse/FELIX-4853?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14500871#comment-14500871
]
Pierre De Rop commented on FELIX-4853:
--------------------------------------
Regarding the java8 example, we can even push the limit of java8 using type
inference:
In the TCCLCallback, we can introduce a static method that can be used to
create a TCCLCallback instance with generic types inferred from the Consumer
parameter:
{code}
/**
* Tool that allows to delegate a dependency callback with TCCL set to the
injected service dependency.
*
* @param <T> The type of the class where the service dependency has to be
injected to, but with TCCL set to the injected service class loader.
* @param <U> The type of the injected service.
*/
public class TCCLCallback<T, U> {
private final BiConsumer<T, U> consumer;
/**
* Creates a TCCLCallback instance with generic types automatically infered
from the consumer parameter.
*/
static <U,V> TCCLCallback<U,V> tccl(BiConsumer<U,V> consumer) {
return new TCCLCallback<U,V>(consumer);
}
public TCCLCallback(BiConsumer<T, U> consumer) {
this.consumer = consumer;
}
void bind(Component component, ServiceReference ref, U service) {
Thread t = Thread.currentThread();
ClassLoader current = t.getContextClassLoader();
Bundle bundle = ref.getBundle();
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
ClassLoader cl = bundleWiring.getClassLoader();
try {
t.setContextClassLoader(cl);
T instance = component.getInstance();
consumer.accept(instance, service);
} finally {
t.setContextClassLoader(current);
}
}
}
{code}
And using the static tccl factory method above, we can now reduce again the
"code ceremony" in the Activator:
{code}
import static tcclcallback.TCCLCallback.tccl;
...
public class Activator extends DependencyActivatorBase {
@Override
public void init(BundleContext bc, DependencyManager dm) throws Exception {
dm.add(createComponent()
.setImplementation(ServiceImpl.class)
.setInterface(Service.class.getName(), null));
dm.add(createComponent()
.setImplementation(Pojo.class)
.add(createServiceDependency()
.setService(Service.class).setCallbacks(tccl(Pojo::bind),
"bind", null)));
}
}
{code}
> Create a new ServiceDependency that sets the TCCL to the incoming
> servicereference bundle's classloader before invoking callbaks
> --------------------------------------------------------------------------------------------------------------------------------
>
> Key: FELIX-4853
> URL: https://issues.apache.org/jira/browse/FELIX-4853
> Project: Felix
> Issue Type: New Feature
> Components: Dependency Manager
> Affects Versions: dependencymanager-3.2.0
> Reporter: Carlos Sierra
> Attachments: examples.tgz
>
>
> The invoke method would go like this:
> {code:title=TCCLServiceDependencyImpl.java|borderStyle=solid}
> @Override
> @SuppressWarnings("rawtypes")
> public void invoke(
> Object[] callbackInstances, DependencyService dependencyService,
> ServiceReference reference, Object service, String name) {
> Bundle bundle = reference.getBundle();
> BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
> ClassLoader bundleClassLoader = bundleWiring.getClassLoader();
> Thread currentThread = Thread.currentThread();
> ClassLoader contextClassLoader =
> currentThread.getContextClassLoader();
> currentThread.setContextClassLoader(bundleClassLoader);
> try {
> super.invoke(
> callbackInstances, dependencyService,
> reference, service, name);
> }
> finally {
> currentThread.setContextClassLoader(contextClassLoader);
> }
> }
> {code}
> If you think this is useful I can provide a patch. Which version and which
> repo should I use for it?
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)