You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by "Marcel Offermans (JIRA)" <ji...@apache.org> on 2014/01/15 10:14:23 UTC

[jira] [Commented] (FELIX-4384) Difference between inner class and normal class service

    [ https://issues.apache.org/jira/browse/FELIX-4384?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13871835#comment-13871835 ] 

Marcel Offermans commented on FELIX-4384:
-----------------------------------------

When reproducing the scenario using the code you provided, I immediately get the following error (I cut away most of the stack trace):

{code}
ERROR: Could not create service instance of class class zzz.dm.Activator$S1. (java.lang.NoSuchMethodException: zzz.dm.Activator$S1.<init>())
java.lang.NoSuchMethodException: zzz.dm.Activator$S1.<init>()
ERROR: Could not register service null (java.lang.IllegalArgumentException: Service object cannot be null.)
java.lang.IllegalArgumentException: Service object cannot be null.
{code}

So your problem is that DM cannot find a default constructor for S1 (or A for that matter). Without an instance, it cannot register the service. If you change the init method as follows:

{code}
        manager.add(createComponent()
            .setInterface(A.class.getName(), null)
            .setImplementation(new A())
            .add(createServiceDependency().setService(S.class).setRequired(true)));

        manager.add(createComponent()
            .setInterface(S.class.getName(), null)
            .setImplementation(new S1()));
{code}

It works:

{code}
g! dm 4
[4] zzz.dm
  zzz.dm.Activator$A() registered
    zzz.dm.Activator$S service required available
  zzz.dm.Activator$S() registered
{code}

Another thing about your code. I noticed you "synchronize" the init and destroy methods. Because you invoke DM methods there, you end up invoking code outside your bundle. For example, if you register a service that someone else is depending on, the registration might trigger the invocation of callback methods in someone else's bundle on that same thread. You cannot hold locks while invoking such methods, because they might end up causing deadlocks (trust me, I've seen a few over the years). In this case, I would simply remove the keyword, since there is no reason for it to be there.

If you agree with my analysis, feel free to close the issue.

> Difference between inner class and normal class service
> -------------------------------------------------------
>
>                 Key: FELIX-4384
>                 URL: https://issues.apache.org/jira/browse/FELIX-4384
>             Project: Felix
>          Issue Type: Bug
>          Components: Dependency Manager
>    Affects Versions: dependencymanager-3.1.0
>            Reporter: Jago de Vreede
>            Priority: Minor
>
> Given the following code:
> package org.example;
> import org.apache.felix.dm.DependencyActivatorBase;
> import org.apache.felix.dm.DependencyManager;
> import org.osgi.framework.BundleContext;
> public class Activator extends DependencyActivatorBase {
>     @Override
>     public synchronized void init(BundleContext context, DependencyManager manager) throws Exception {
>         manager.add(createComponent()
>             .setInterface(A.class.getName(), null)
>             .setImplementation(A.class)
>             .add(createServiceDependency().setService(S.class).setRequired(true)));
>         
>         manager.add(createComponent()
>             .setInterface(S.class.getName(), null)
>             .setImplementation(S1.class));
>     }
>     @Override
>     public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {}
>     
>     interface S {}
>     class A {}
>     class S1 implements S {}
> }
> dm will print out:
> g! dm
> [8] mytest
>  [0] org.example.Activator$A unregistered
>     org.example.Activator$S service required unavailable
>  [1] org.example.Activator$S registered
> But when the class S1 is promoted to a real class, dm will print out:
> g! dm
> [8] mytest
>  [0] org.example.Activator$A registered
>     org.example.Activator$S service required available
>  [1] org.example.Activator$S registered
> So the service class S1 is not available if its an inner class but is available if its a normal class.



--
This message was sent by Atlassian JIRA
(v6.1.5#6160)