[Design of Clustering on JBoss (Clusters/JBoss)] - Re: JBAS-4180 - HA <-> JMX coupling
by bstansberry@jboss.com
HASingletonController can have the target bean directly injected, in which case it will not invoke the target's methods via JMX.
Your comment about @StartSingleton, etc. is valid, but lets defer to a different discussion. Not going to happen for beta3.
What does a class gain by subclassing ServiceMBeanSupport:
1) Benefits from the lifecycle coding. Stuff that prevents startService() being called again when service is already started, etc.
2) Support for exposing service lifecycle state as an mbean attribute (getState())
3) I gets a ref to the mbean server when an instance is registered in JMX. Can use that to make JMX calls.
4) Probably others; part of task is to identify and see if relevant
1) and 2) are conceptually different from 3). Illustration:
Class implements the lifecycle methods; deployed by MC as a pojo service. MC invokes lifecycle methods.
In the -beans.xml the bean is annotated with @JMX. Sole purpose of this is to get the bean registered in JMX. Doing this is not a functional requirement of the class; it's a deployment decision for *that particular instance of the class*. MC will create a JMX proxy to the service and deploy that as well. When the proxy is deployed, the create/start/stop/destroy methods get called *again*. This is where benefit 1) is useful. You could get the same benefit by coding equivalent #1 functionality in the bean class itself, or in some PojoServiceSupport superclass.
If the class needs to use the mbean server to do its work, then you start getting into benefit #3. You need a ref to the server.
What I want here is the #3 cases isolated, particularly for the HASingletonController/HASingletonSupport. That class should be usable without it having a ref to an MBeanServer if:
1) user doesn't need the JMX notifications
2) user configures the deployment to dependency inject the target rather than injecting an ObjectName.
3) Other things you might find by digging.
Don't worry about making DetachedHANamingService not extend ServiceMBeanSupport. It's the singleton stuff where I can imagine wanting to have a lot of deployment flexibility.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4091148#4091148
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4091148
18 years, 2 months
[Design of Clustering on JBoss (Clusters/JBoss)] - Re: JBAS-4180 - HA <-> JMX coupling
by galder.zamarreno@jboss.com
"bstansberry(a)jboss.com" wrote :
| anonymous wrote :
| | 3. HASingletonController does nothing JMX related, except publicise (via getters) the configuration options for target start/stop methods. Needs JMX factoring out IMO.
| |
| The barrier counts on the notifications, and other users may be counting on the notifications as well, so if there is a refactoring to provide a non-JMX version, the std HASingletonController class needs to provide the notifications.
|
Not sure I understand what you mean here. HASingletonSupport provides the notifications, not HASingletonController. HASingletonController just extends the start/stop singleton methods that are called by HASingletonSupport. In between the call to these methods, HASingletonSupport sends the notifications.
HASingletonController, using the configured target methods, within start/stop singleton methods, calls them via the mbean server.
>From this point of view, not sure what we gain by having HASingletonController extend HASingletonSupport and so extend ServiceMBeanSupport.
I'm not sure how to do this cos I know little about MC, but any call to lifecycle methods (read singleton lifecycle) methods should really be done by the MC, shouldn't it? Other than that, HASingletonController just tells what are these methods. Maybe HASingletonController could just go?
Maybe we could create @StartSingleton/@StopSingleton annotations and target beans could annotate such methods with these annotations. The MC then can call them. I might be talking absolute rubbish here though! :)
How HASingletonSupport would instruct MC to do this is unknown to me.
"bstansberry(a)jboss.com" wrote :
| anonymous wrote :
| | + HASingletonElectionPolicyBase and HASingletonElectionPolicySimple
| |
| | This is new functionality to decide where to run HA singleton services instead of the coordinator. It makes sense to factor JMX out of these classes to separate functionality from any JMX managed methods. An election policy should be independent, like the load balance policies.
| |
|
| +1.
|
TODO1 for JBAS-4180
"bstansberry(a)jboss.com" wrote :
| anonymous wrote :
| | + ClusterPartition
| |
| | Does not make sense to have a non JMX version.
| |
|
| Sure it does. Again, the issue here is whether classes extend ServiceMBeanSupport, not whether they expose a JMX interface.
|
| That said, changing this isn't a priority.
|
Hmmmm, I guess it'd make unit testing CP a lot easier if it didn't extend ServiceMBeanSupport? Other than that, I don't see it being used standalone to provide a non ServiceMBeanSupport extending version.
"bstansberry(a)jboss.com" wrote :
| anonymous wrote :
| | To factor out JMX from invokers makes sense to help unit testing and potentially make path for them to be migrated to Remoting (there's a JIRA on this) and be used standalone. It would also make my life a lot easier unit testing JBAS-4455 :)
| |
|
| Sadly, unlikely to happen before beta3 and thus not in 5.0.0. In any case, this should be driven by what's done with the non-HA version.
|
Not a TODO of JBAS-4180
"bstansberry(a)jboss.com" wrote :
| anonymous wrote :
| | + DetachedHANamingService and HANamingService
| |
| | DetachedHANamingService uses JMX (via Query) to find an HAPartition with a given name via findHAPartitionWithName method. Couldn't find any references to this method and it's not a managed method either.
| |
|
| That method should be removed; the partition should be dependency injected. I'm quite sure it already is injected; that method is probably just leftover cruft.
|
TODO2 for JBAS-4180, remove the findHAPartitionWithName method.
What about whether DetachedHANamingService and HANamingService should extend ServiceMBeanSupport?
"bstansberry(a)jboss.com" wrote :
| anonymous wrote :
| | + PingJndi
| | ...
| |
|
| ... Don't even know what PingJndi is.
|
Hidden gem maybe? hehehe ;)
"bstansberry(a)jboss.com" wrote :
| Thanks much for this. Even if we don't change much for 5.0.0 this is most helpful.
no probs :-D
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4091129#4091129
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4091129
18 years, 2 months
[Design of JBoss jBPM] - JobExecutor enhencement proposition to allow 3rd framework i
by p.pasqual
Hi all,
I work currently on integartion of Jbpm solution under our Software which is base on Spring Framwork : using Spring bean for configuration and AOP interception for transactional and logging stuff.
An Custom ObjectFactory implementation permit to use bean configuration
made under "Spring Beans" if existe and use default ObjectFactoryImpl if not.
JobExecutor 's Fields are all "package" , and there is no relative "public" setter, soo it's impossible to set values from a Spring Bean Context. One of the simplest way to solve this is to simply add setters for all field present under jbpm.cfg.xml file.
Un other point is About posibility to use Spring AOP transaction interception
during assynchronous Job Execution (ie Using transaction context of hosting platform of course if provided). For this i propose to un-couple JbpmContext technical (aquire/close/exception handling) and functional (Job Execution) stuff using Service/Callback writing pattern.
Enhencement Resume :
1/ JobExecutor setter Add
2/ JobExecutorThread execution actions under host provided transactional context.
To give you an idee i send you a "draft" patch corresponding to my implementation. I made it to limite impact at the minimum on code base. At the first aproche i only refactor JobExecutorThread.executeJob() to use Callback but i think it's possible to extends this methodology to all other point where there is JbpmContext creation.
i waiting for your feed back
best regards
|
| Index: src/jpdl/org/jbpm/job/executor/JobExecutor.java
| ===================================================================
| --- src/jpdl/org/jbpm/job/executor/JobExecutor.java (revision 20)
| +++ src/jpdl/org/jbpm/job/executor/JobExecutor.java (working copy)
| @@ -15,11 +15,14 @@
| import org.apache.commons.logging.LogFactory;
| import org.jbpm.JbpmConfiguration;
|
| +
| public class JobExecutor implements Serializable {
|
| private static final long serialVersionUID = 1L;
|
| JbpmConfiguration jbpmConfiguration;
| + JobExecutorService jobExecutorService;
| +
| String name;
| int nbrOfThreads;
| int idleInterval;
| @@ -164,6 +167,57 @@
| public int getNbrOfThreads() {
| return nbrOfThreads;
| }
| +
| + public void setLockMonitorThread(LockMonitorThread in_lockMonitorThread) {
| + lockMonitorThread = in_lockMonitorThread;
| + }
| +
| + public void setJbpmConfiguration(JbpmConfiguration in_jbpmConfiguration) {
| + jbpmConfiguration = in_jbpmConfiguration;
| + }
| +
| + public void setName(String in_name) {
| + name = in_name;
| + }
| +
| + public void setIdleInterval(int in_idleInterval) {
| + idleInterval = in_idleInterval;
| + }
| +
| + public void setMaxIdleInterval(int in_maxIdleInterval) {
| + maxIdleInterval = in_maxIdleInterval;
| + }
| +
| + public void setHistoryMaxSize(int in_historyMaxSize) {
| + historyMaxSize = in_historyMaxSize;
| + }
| +
| + public void setMaxLockTime(int in_maxLockTime) {
| + maxLockTime = in_maxLockTime;
| + }
| +
| + public void setLockMonitorInterval(int in_lockMonitorInterval) {
| + lockMonitorInterval = in_lockMonitorInterval;
| + }
| +
| + public void setLockBufferTime(int in_lockBufferTime) {
| + lockBufferTime = in_lockBufferTime;
| + }
| +
| + public void setNbrOfThreads(int in_nbrOfThreads) {
| + nbrOfThreads = in_nbrOfThreads;
| + }
| +
| + public JobExecutorService getJobExecutorService() {
| + if (jobExecutorService == null){
| + jobExecutorService = new JobExecutorServiceImpl(this);
| + }
| + return jobExecutorService;
| + }
| +
| + public void setJobExecutorService(JobExecutorService in_jobExecutorService) {
| + jobExecutorService = in_jobExecutorService;
| + }
|
| private static Log log = LogFactory.getLog(JobExecutor.class);
| }
| Index: src/jpdl/org/jbpm/job/executor/JobExecutorCallback.java
| ===================================================================
| --- src/jpdl/org/jbpm/job/executor/JobExecutorCallback.java (revision 0)
| +++ src/jpdl/org/jbpm/job/executor/JobExecutorCallback.java (revision 0)
| @@ -0,0 +1,18 @@
| +package org.jbpm.job.executor;
| +
| +import org.jbpm.JbpmContext;
| +
| +/**
| + *
| + * @author p.pasqual
| + *
| + */
| +public interface JobExecutorCallback {
| +
| + /**
| + *
| + * @param in_context
| + * @return
| + */
| + public Object doInJobExecutor(JbpmContext in_jbpmContext);
| +}
| Index: src/jpdl/org/jbpm/job/executor/JobExecutorService.java
| ===================================================================
| --- src/jpdl/org/jbpm/job/executor/JobExecutorService.java (revision 0)
| +++ src/jpdl/org/jbpm/job/executor/JobExecutorService.java (revision 0)
| @@ -0,0 +1,15 @@
| +package org.jbpm.job.executor;
| +
| +/**
| + *
| + * @author p.pasqual
| + *
| + */
| +public interface JobExecutorService {
| +
| + /**
| + *
| + * @param in_callback
| + */
| + public void execute(JobExecutorCallback in_callback);
| +}
| Index: src/jpdl/org/jbpm/job/executor/JobExecutorServiceImpl.java
| ===================================================================
| --- src/jpdl/org/jbpm/job/executor/JobExecutorServiceImpl.java (revision 0)
| +++ src/jpdl/org/jbpm/job/executor/JobExecutorServiceImpl.java (revision 0)
| @@ -0,0 +1,53 @@
| +package org.jbpm.job.executor;
| +
| +import org.apache.commons.logging.Log;
| +import org.apache.commons.logging.LogFactory;
| +import org.jbpm.JbpmContext;
| +
| +import org.jbpm.persistence.JbpmPersistenceException;
| +import org.jbpm.persistence.db.StaleObjectLogConfigurer;
| +
| +public class JobExecutorServiceImpl implements JobExecutorService {
| +
| + private final JobExecutor jobExecutor;
| +
| + public JobExecutorServiceImpl(JobExecutor in_jobExecutor) {
| + super();
| + jobExecutor = in_jobExecutor;
| + }
| +
| + public void execute(JobExecutorCallback callback) {
| + JbpmContext jbpmContext = aquireContext();
| + try {
| + callback.doInJobExecutor(jbpmContext);
| + } finally {
| + try {
| + jbpmContext.close();
| + } catch (JbpmPersistenceException e) {
| + // if this is a stale object exception, the jbpm configuration
| + // has control over the logging
| + if ("org.hibernate.StaleObjectStateException".equals(e.getCause().getClass().getName())) {
| + log.info("problem committing execution transaction: optimistic locking failed");
| + StaleObjectLogConfigurer.staleObjectExceptionsLog.error("problem committing job execution transaction: optimistic locking failed", e);
| + } else {
| + log.error("problem committing execution transaction", e);
| + }
| + } catch (RuntimeException e) {
| + log.error("problem committing execution transaction", e);
| +
| + throw e;
| + }
| + }
| + }
| +
| + protected JbpmContext aquireContext(){
| + return getJobExecutor().getJbpmConfiguration().createJbpmContext();
| + }
| +
| + protected JobExecutor getJobExecutor() {
| + return jobExecutor;
| + }
| +
| + private static Log log = LogFactory.getLog(JobExecutorServiceImpl.class);
| +
| +}
| Index: src/jpdl/org/jbpm/job/executor/JobExecutorThread.java
| ===================================================================
| --- src/jpdl/org/jbpm/job/executor/JobExecutorThread.java (revision 20)
| +++ src/jpdl/org/jbpm/job/executor/JobExecutorThread.java (working copy)
| @@ -17,8 +17,6 @@
| import org.jbpm.db.JobSession;
| import org.jbpm.job.Job;
| import org.jbpm.job.Timer;
| -import org.jbpm.persistence.JbpmPersistenceException;
| -import org.jbpm.persistence.db.StaleObjectLogConfigurer;
|
| public class JobExecutorThread extends Thread {
|
| @@ -153,50 +151,38 @@
| return acquiredJobs;
| }
|
| - protected void executeJob(Job job) {
| - JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
| - try {
| - JobSession jobSession = jbpmContext.getJobSession();
| - job = jobSession.loadJob(job.getId());
| + protected void executeJob(final Job todo) {
| + jobExecutor.getJobExecutorService().execute(new JobExecutorCallback() {
| + public Object doInJobExecutor(JbpmContext jbpmContext) {
| + JobSession jobSession = jbpmContext.getJobSession();
| + Job job = jobSession.loadJob(todo.getId());
|
| - try {
| - log.debug("executing job "+job);
| - if (job.execute(jbpmContext)) {
| - jobSession.deleteJob(job);
| - }
| + try {
| + log.debug("executing job " + job);
| + if (job.execute(jbpmContext)) {
| + jobSession.deleteJob(job);
| + }
|
| - } catch (Exception e) {
| - log.debug("exception while executing '"+job+"'", e);
| - StringWriter sw = new StringWriter();
| - e.printStackTrace(new PrintWriter(sw));
| - job.setException(sw.toString());
| - job.setRetries(job.getRetries()-1);
| - }
| -
| - // if this job is locked too long
| - long totalLockTimeInMillis = System.currentTimeMillis() - job.getLockTime().getTime();
| - if (totalLockTimeInMillis>maxLockTime) {
| - jbpmContext.setRollbackOnly();
| - }
| + } catch (Exception e) {
| + log.debug("exception while executing '" + job + "'", e);
| + StringWriter sw = new StringWriter();
| + e.printStackTrace(new PrintWriter(sw));
| + job.setException(sw.toString());
| + job.setRetries(job.getRetries() - 1);
| + }
|
| - } finally {
| - try {
| - jbpmContext.close();
| - } catch (JbpmPersistenceException e) {
| - // if this is a stale object exception, the jbpm configuration has control over the logging
| - if ("org.hibernate.StaleObjectStateException".equals(e.getCause().getClass().getName())) {
| - log.info("problem committing job execution transaction: optimistic locking failed");
| - StaleObjectLogConfigurer.staleObjectExceptionsLog.error("problem committing job execution transaction: optimistic locking failed", e);
| - } else {
| - log.error("problem committing job execution transaction", e);
| - }
| - } catch (RuntimeException e) {
| - log.error("problem committing job execution transaction", e);
| + // if this job is locked too long
| + long totalLockTimeInMillis = System.currentTimeMillis() - job.getLockTime().getTime();
| + if (totalLockTimeInMillis > maxLockTime) {
| + jbpmContext.setRollbackOnly();
| + }
|
| - throw e;
| - }
| - }
| - }
| + return null;
| + }
| + });
| +
| + }
| +
| protected Date getNextDueDate() {
| Date nextDueDate = null;
| JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
|
|
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4091111#4091111
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4091111
18 years, 2 months