-
1. Re: How to implement a hasingleton service in as7?
ctomc Jan 12, 2012 1:10 PM (in response to kc7bfi)Hi,
I don't know the specifics about ha singleton. But support for them was added in version 7.1.0.CR1
you can read about it in jira: https://issues.jboss.org/browse/AS7-2958
and take a look at arq test https://github.com/jbossas/jboss-as/blob/master/testsuite/integration/clust/src/test/java/org/jboss/as/test/clustering/unmanaged/singleton/SingletonTestCase.java
hope anything of this helps.
cheers,
tomaž
-
2. Re: How to implement a hasingleton service in as7?
martijnzuidhof Feb 2, 2012 3:24 AM (in response to kc7bfi)Hi,
We are in the same situation.. I was wondering if you had found a solution for this?
kind regards,
Martijn
-
3. Re: How to implement a hasingleton service in as7?
kc7bfi Feb 6, 2012 9:12 AM (in response to martijnzuidhof)Here is my solution:
The MBean for the service controlling the singleton (DummySingletonSvcMBean.java)
package com.orci.TravelTimeEngine.dummy;
public interface DummySingletonSvcMBean {
/**
* stop the service.
*/
void stop();
/**
* start the service.
* @throws Exception error
*/
void start() throws Exception;
}
The actual service controlling the singleton (DummySingletonSvc.java)
package com.orci.TravelTimeEngine.dummy;
import java.util.Collection;
import java.util.EnumSet;
import org.jboss.as.clustering.singleton.SingletonService;
import org.jboss.as.clustering.singleton.election.NamePreference;
import org.jboss.as.clustering.singleton.election.PreferredSingletonElectionPolicy;
import org.jboss.as.clustering.singleton.election.SimpleSingletonElectionPolicy;
import org.jboss.as.server.CurrentServiceContainer;
import org.jboss.as.server.ServerEnvironment;
import org.jboss.as.server.ServerEnvironmentService;
import org.jboss.logging.Logger;
import org.jboss.msc.service.AbstractServiceListener;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceController.Transition;
import org.jboss.msc.service.ServiceListener;
import com.orci.TravelTimeEngine.hibernate.utils.ThreadTransaction;
public class DummySingletonSvc implementsDummySingletonSvcMBean {
private static final Logger LOG = Logger.getLogger(DummySingletonSvc.class.getName());
private DummySvc service;
private ServiceController<String> controller;
/**
* {@inheritDoc}
*/
@Override
public void start() throws Exception {
LOG.info("Starting service...");
ThreadTransaction.init();
String preferedNode = System.getProperty("DummySvc.PreferedNode", "tte-processor-01");
service = new DummySvc();
SingletonService<String> singleton = new SingletonService<String>(service, DummySvc.SERVICE_NAME);
singleton.setElectionPolicy(new PreferredSingletonElectionPolicy(new NamePreference(preferedNode + "/" + SingletonService.DEFAULT_CONTAINER), new SimpleSingletonElectionPolicy()));
controller = singleton.build(CurrentServiceContainer.getServiceContainer())
.addDependency(ServerEnvironmentService.SERVICE_NAME, ServerEnvironment.class, service.getEnvInjector())
.install()
;
controller.setMode(ServiceController.Mode.ACTIVE);
wait(controller, EnumSet.of(ServiceController.State.DOWN, ServiceController.State.STARTING), ServiceController.State.UP);
LOG.info("Start done");
}
/**
* {@inheritDoc}
*/
@Override
public void stop() {
LOG.info("Stopping service...");
service.stop(null);
controller.setMode(ServiceController.Mode.REMOVE);
wait(controller, EnumSet.of(ServiceController.State.UP, ServiceController.State.STOPPING, ServiceController.State.DOWN), ServiceController.State.REMOVED);
LOG.info("Stop done");
}
/**
* Wait for the controller state.
* @param controller the controller
* @param expectedStates the expected sates
* @param targetState the target state
* @param <T> the type
*/
private static <T> void wait(ServiceController<T> controller, Collection<ServiceController.State> expectedStates, ServiceController.State targetState) {
if (controller.getState() != targetState) {
ServiceListener<T> listener = new NotifyingServiceListener<T>();
controller.addListener(listener);
try {
synchronized (controller) {
while (expectedStates.contains(controller.getState())) {
LOG.info(String.format("Service controller state is %s, waiting for transition to %s", controller.getState(), targetState));
controller.wait();
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
controller.removeListener(listener);
ServiceController.State state = controller.getState();
if (state != targetState) {
throw new IllegalStateException(String.format("Failed to wait for state to transition to %s. Current state is %s", targetState, state), controller.getStartException());
}
}
}
private static class NotifyingServiceListener<T> extends AbstractServiceListener<T> {
@Override
public void transition(ServiceController<? extends T> controller, Transition transition) {
synchronized (controller) {
controller.notify();
}
}
}
}
Here is the actual singleton service (DummySvc)
package com.orci.TravelTimeEngine.AwamDataProvidor;
import java.util.Date;
import java.util.Timer;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jboss.as.server.ServerEnvironment;
import org.jboss.logging.Logger;
import org.jboss.msc.inject.Injector;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
import org.jboss.msc.value.InjectedValue;
import com.orci.commons.lang.properties.PropertyFileListener;
import com.orci.commons.lang.properties.PropertyFileWatcher;
public class DummySvc implements Service<String>, PropertyFileListener {
private static final Logger LOG = Logger.getLogger(DummySvc.class.getName());
public static final ServiceName SERVICE_NAME = ServiceName.JBOSS.append("orci", "DummySvc");
private final InjectedValue<ServerEnvironment> env = new InjectedValue<ServerEnvironment>();
private final AtomicBoolean started = new AtomicBoolean(false);
/**
* @return the environment
*/
public Injector<ServerEnvironment> getEnvInjector() {
return this.env;
}
@Override
public String getValue() throws IllegalStateException, IllegalArgumentException {
return null;
}
/**
* {@inheritDoc}
*/
@Override
public void start(StartContext ctx) throws StartException {
LOG.info("Starting singleton service...");
LOG.info("Start singleton done");
}
/**
* {@inheritDoc}
*/
@Override
public void stop(StopContext ctx) {
LOG.info("Stopping singleton service...");
LOG.info("Stop singleton done");
}
}
Hope this helps
-
4. Re: How to implement a hasingleton service in as7?
vithun.v Feb 8, 2012 2:07 AM (in response to kc7bfi)I'm facing the same problem here!, Even i taught of the solution David Robison has given, but I'm not sure whether its a good practice to deploy/undeploy ourselves (I dont actually know). Do we have any other alternative to deploy this kind of application. In other words, what is the JBOSS recommended way of migrating application that used to be deployed in deploy-hasingleton directory. Application that wiill be active only on one machine at once.
-
5. Re: How to implement a hasingleton service in as7?
wutongjoe Mar 9, 2012 3:39 AM (in response to kc7bfi)This worked as read value from hasingleton,but how do we set value to a hasingleton? any idea?
Thanks a lot
-
6. Re: How to implement a hasingleton service in as7?
wesjanik May 17, 2012 1:02 PM (in response to kc7bfi)David - Thanks for the complete example on how to accomplish this.
Does anyone know if there is a way to accomplish the same goal without the service MBean code (DummySingletonSvc), and dependence on the Service interface in David's example? Maybe some kind of MBean XML configuration? I'm still fuzzy on what can and cannot be done via MBean XML, so I can't really tell if this is an option or not. The bottom line is I'm hoping to avoid adding JBoss-specific library dependencies in my source, and instead do everything with JBoss-specific configuration.
-
7. Re: How to implement a hasingleton service in as7?
pferraro May 18, 2012 12:17 PM (in response to wesjanik)In short, there's no way to do this without exposing JBoss specific dependencies - there is no standard API for clustered singletons. You could get away with this in older JBoss releases by adhering to lifecycle method conventions (e.g. create(), start(), stop(), destroy()). In constrast, AS7 uses org.jboss.msc.Service to define component lifecycle - thus the dependency on its interface.
Also, to address some of the confusion between the deploy-hasingleton directory approach in older JBoss releases and the SingletonService approach in AS7:
The deploy-hasingleton logic achieved the goal of having a target service started on only 1 node in a cluster at a time by only deploying the service on one node at any given time. In constrast, using SingletonService in AS7, the target service will be installed on every node in the cluster, but is only ever started on one node at any given time. This approach both simplifies deployment requirements and minimizes the time required to relocate the singleton master between nodes.
-
8. Re: How to implement a hasingleton service in as7?
pferraro May 18, 2012 12:21 PM (in response to wutongjoe)Singleton services are not meant to behave like a clustered cache. If you want the ability to make a set of data available to all nodes in your cluster, consider using an Infinispan cache.
-
9. Re: How to implement a hasingleton service in as7?
wesjanik May 21, 2012 11:34 AM (in response to pferraro)Makes sense now... Thanks for the quick response!
-
10. Re: How to implement a hasingleton service in as7?
fred.vogt Jun 22, 2012 4:45 AM (in response to kc7bfi)David, your example doesn't redeploy cleanly.
There is two other MSC services that must be removed by your context listener: ServiceName SERVICE_NAME."service" and ServiceName SERVICE_NAME."singleton"
When the application is redeployed these services are added, if they already exist you get a duplicate service exception.
-
11. Re: How to implement a hasingleton service in as7?
radzish Jun 22, 2012 8:26 AM (in response to fred.vogt)You saved my day, Fred. Thanks a lot.
-
12. Re: How to implement a hasingleton service in as7?
pferraro Jun 26, 2012 11:09 AM (in response to fred.vogt)I've opened https://issues.jboss.org/browse/AS7-5073 so that we auto-remove these child services when the parent service is removed.