6 Replies Latest reply on Jul 18, 2016 8:42 PM by Yannick Menager

    What happened to ChannelService?

    Dave Rathnow Novice

      I have been using EAP 6.2 for a couple of years now and want to move over to Wildfly 10.  After going through some initial configuration, I tried to deploy my app and hit a snag.

       

      When I first wrote my app, I needed to get access to LockService so I could create my own cluster wide locks.  Paul Ferraro was kind enough to help me out in this post Re: Using jgroups CounterService with jboss's cluster channel, and everything was good under EAP.  However, when I try to deploy under Wildfly 10, I'm getting the following exception:

       

      Caused by: java.util.ServiceConfigurationError: org.jboss.msc.service.ServiceActivator: Provider zedi.pacbridge.app.msc.MyLockServiceActivator could not be instantiated

        at java.util.ServiceLoader.fail(ServiceLoader.java:232)

        at java.util.ServiceLoader.access$100(ServiceLoader.java:185)

        at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:384)

        at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)

        at java.util.ServiceLoader$1.next(ServiceLoader.java:480)

        at org.jboss.as.server.deployment.service.ServiceActivatorProcessor.deploy(ServiceActivatorProcessor.java:72)

        at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:147)

        ... 5 more

      Caused by: java.lang.NoClassDefFoundError: org/jboss/as/clustering/jgroups/subsystem/ChannelService

        at zedi.pacbridge.app.msc.MyLockServiceActivator.<clinit>(MyLockServiceActivator.java:27)

        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)

        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

        at java.lang.reflect.Constructor.newInstance(Constructor.java:422)

        at java.lang.Class.newInstance(Class.java:442)

        at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380)

        ... 9 more

      Caused by: java.lang.ClassNotFoundException: org.jboss.as.clustering.jgroups.subsystem.ChannelService from [Module "deployment.pacbridge-ear-6.1.0.RC-1.ear.pacbridge-app-6.1.0.jar:main" from Service Module Loader]

        at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:198)

        at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:363)

        at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:351)

        at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:93)

        ... 16 more

       

      I hunted through the Wildfly 10 jarfiles and discovered that ChannelService isn't there anymore.  Has the name changed?  Is there another way to get access to the LockService in Wildfly 10?

       

      Thanks.

        • 1. Re: What happened to ChannelService?
          Paul Ferraro Master

          drathnow ChannelService was never public API and there was some significant refactoring of how services obtain and create channels.  Can you paste your code that uses ChannelService from EAP6.2, and I'll show you how best to adapt this to WF10, ideally using public (i.e. stable) APIs.

          • 2. Re: What happened to ChannelService?
            Dave Rathnow Novice

            Thanks for the reply @Paul Ferraro,

             

            T@hat would explain it.  What I really need is way to create distributed locks so I can do cluster wide locking.  i.e. I need to get access to the LockService.  If there's a better, supported way to do that under wildfly, then perhaps you could tell me.  For now, here's he code that I was using under EAP 6.2

             

                public static final String CLUSTER_NAME = "cluster-channel";

                public static final ServiceName CHANNEL_SERVICE_NAME = ChannelService.getServiceName(CLUSTER_NAME);

                public static final ServiceName LOCK_SERVICE_NAME = CHANNEL_SERVICE_NAME.append("lock-service");

                public static final String JNDI_NAME = "java:jboss/myapp/cluster-lock-service";

              

                @Override

                public void activate(ServiceActivatorContext context) {

                    ServiceTarget serviceTarget = context.getServiceTarget();

                    createLockService(serviceTarget);

                    createChannelService(serviceTarget);

                    bindJndiResource(serviceTarget);      

                }

              

                private void createLockService(ServiceTarget serviceTarget) {

                    InjectedValue<Channel> channel = new InjectedValue<Channel>();

                    serviceTarget.addService(LOCK_SERVICE_NAME, new MyLockService(channel, CLUSTER_NAME))

                        .addDependency(CHANNEL_SERVICE_NAME, Channel.class, channel)

                        .setInitialMode(ServiceController.Mode.ACTIVE)

                        .install();

                }

             

             

                private void createChannelService(ServiceTarget serviceTarget) {

                    InjectedValue<ChannelFactory> factory = new InjectedValue<ChannelFactory>();

                    serviceTarget.addService(CHANNEL_SERVICE_NAME, new ChannelService(CLUSTER_NAME, factory))

                        .addDependency(ChannelFactoryService.getServiceName(null), ChannelFactory.class, factory)

                        .setInitialMode(ServiceController.Mode.ON_DEMAND)

                        .install();

                }

              

                private void bindJndiResource(ServiceTarget serviceTarget) {

                    ContextNames.BindInfo bindInfo = ContextNames.bindInfoFor(JNDI_NAME);

                    BinderService binder = new BinderService(bindInfo.getBindName());

                    serviceTarget.addService(bindInfo.getBinderServiceName(), binder)

                        .addAliases(ContextNames.JAVA_CONTEXT_SERVICE_NAME.append(JNDI_NAME))

                        .addDependency(LOCK_SERVICE_NAME, LockService.class, new ManagedReferenceInjector<LockService>(binder.getManagedObjectInjector()))

                        .addDependency(bindInfo.getParentContextServiceName(), ServiceBasedNamingStore.class, binder.getNamingStoreInjector())

                        .setInitialMode(ServiceController.Mode.PASSIVE)

                        .install();

                }

            • 3. Re: What happened to ChannelService?
              Paul Ferraro Master

              In WildFly 10 you don't need to create a channel service - you can declare your channel in your JGroups subsystem configuration.  Each channel (and fork channel) declared in the JGroups subsystem is exposed as a Service<Channel>.

               

              The service name of your channel can be generated via:

              org.wildfly.clustering.jgroups.spi.service.ChannelServiceName.CHANNEL.getServiceName("your-channel-name");
              

               

              You will also want to add a dependency on the "org.wildfly.clustering.jgroups.spi" module, instead of the "org.jboss.as.clustering.jgroups" module.

               

              WildFly 10 also exposes JGroups channels via jndi.

              e.g.

              @Resource(lookup = "java:jboss/jgroups/channel/your-channel-name")
              private Channel channel;
              

              Using the injected channel, you could easily create and start your LockService via a CDI producer and inject it wherever you need it.

              • 4. Re: What happened to ChannelService?
                Yannick Menager Newbie

                Hi Paul,

                 

                The JNDI approach doesn't seem to work for non-default / system channels (so 'ee', 'web', 'hibernate', etc).... Any other ones that I add to the to xml contig seem to be ignore... any idea why ?

                • 5. Re: What happened to ChannelService?
                  Paul Ferraro Master

                  Channels are only registered to JNDI when the channel is connected.  I suspect that the reason your application cannot find the channel is because there is no service that automatically creates/connect it.  Consequently, you'll want to create and connect your channel from a ChannelFactory. WildFly exposes a ChannelFactory per jgroups stack (i.e. a ChannelFactory that creates a JChannel) - as well as per JGroups channel (i.e. a ChannelFactory that creates ForkChannels). Now that WildFly 10 no longer uses a shared transport, you should never create more than 1 channel per stack, but can create any number of fork channels per JChannel.  From your application's perspective, a ForkChannel will behave the same as a JChannel, but internally, will share the resources (protocols, thread pools, etc) of the JChannel from which it was constructed.

                  e.g.java:jboss/jgroups/factory/default

                  @Resource(lookup = "java:jboss/jgroups/factory/default")
                  private ChannelFactory factory;
                  private Channel channel;
                  
                  @PostConstruct
                  public void init() {
                     this.channel = this.factory.createChannel("...");
                     this.channel.connect("...");
                  }
                  
                  @PreDestroy
                  public void destroy() {
                     this.channel.disconnect();
                     this.channel.close();
                  }
                  

                  N.B. java:jboss/jgroups/factory/default refers to the default channel factory of the server.

                   

                  What exactly do you intended to do with the channel?

                  • 6. Re: What happened to ChannelService?
                    Yannick Menager Newbie

                    Thanks Paul !!

                     

                    My application already uses jgroup as a kind of "JMS-lite" to notify all servers of events which some of them might care (or not, depending on which clients are connected to it), so I wanted to adapt the code to be able to reuse the wildfly jgroup channels to avoid duplication.