ã¯ããã«
Apache Camelã¢ãã«ã¯ã«ãŒãã®æŠå¿µã«åºã¥ããŠãããéçã«ïŒããšãã°ãSpringã³ã³ããã¹ããã¡ã€ã«ã§ïŒãŸãã¯ã¢ããªã±ãŒã·ã§ã³ã®å®è¡äžã«æ§æã§ããŸãã ã¡ãã»ãŒãžã®ãã£ã©ãã³ã¯ãããŸããŸãªããã»ããµãŒãã³ã³ããŒã¿ãŒãã¢ã°ãªã²ãŒã¿ãŒãããã³ãã®ä»ã®ãã©ã³ã¹ãã©ãŒããŒã«å¶ç¶åé¡ãããã«ãŒãã«æ²¿ã£ãŠç§»åããŸãã
äžè¬ã«ãCamelã¯å®å šã«èªå·±å®çµåã®ãã¬ãŒã ã¯ãŒã¯ã§ãã ããã䜿çšãããšãå€ãã®å Žåãç¬èªã®ã³ãŒããäœæããå¿ èŠãããããŸãããåé¡ã解決ããæ£ããã«ãŒãããã€ã€ã«ããã ãã§ãã ãã ããç¬èªã®ããŒã¿åŠçã¢ãã«ãæ§ç¯ããã«ã¯ãã³ãŒããèšè¿°ããå¿ èŠããããŸãã
ã ãããç§ãã¡ãšäžç·ã§ããã ãã£ã¡ã«ã䜿çšããŠãããŸããŸãªãœãŒã¹ããã®è€æ°ã®ã¡ãã»ãŒãžãåŠçããããã®ãã€ãã©ã€ã³ãå®è£ ããŸãã ãã®ãããªã¢ãããŒãã«ãããããšãã°ããµãŒãã¹ã®ã¹ããŒã¿ã¹ã®ç£èŠãåé¡ã®ã¿ã€ã ãªãŒãªéç¥ãéçŽãããåæã¹ã©ã€ã¹ã®åä¿¡ãä»ã®ã·ã¹ãã ã«éä¿¡ããããã®ããŒã¿ã®æºåãªã©ãå¯èœã«ãªããŸãã ã·ã¹ãã ãžã®åŠçæžã¿ããã³ãæ¶åå¯èœãªãã¡ãã»ãŒãžã®ãããŒã¯éåžžã«å€§ãããªãå¯èœæ§ãããããïŒ1åãããæ°åã®ã¡ãã»ãŒãžïŒãå¯èœãªéãæ°Žå¹³æ¹åã«ã¹ã±ãŒã©ãã«ãªãœãªã¥ãŒã·ã§ã³ã䜿çšããããšããŸãã ããšãã°ãå®è¡äžã®ãã¹ãã®ã¹ããŒã¿ã¹ãç£èŠãããµãŒãã¹ãç£èŠããã·ã¹ãã ããããŸãã ãã®ãããªãã¹ãã¯æ¯æ¥100äžä»¶ããããããã®å®è¡ããã»ã¹ãå¶åŸ¡ããããã«äœåºŠãã¡ãã»ãŒãžãåãåããŸãã
ãã®ãããªå€§éã®ã¡ãã»ãŒãžããååãããããã«ã¯ãéçŽæŠç¥ãæ確ã«å®çŸ©ããå¿ èŠããããŸã-åæå®è¡æ§ã®é«ããã®ããå°ãªããã®ãžã ããã«ãå°ãªããšãåºæ¬çãªæ°Žå¹³ã¹ã±ãŒã©ããªãã£ãšãµãŒãã¹ã®ãã©ãŒã«ããã¬ã©ã³ã¹ãå¿ èŠã§ãã
ActiveMQãã¡ãã»ãŒãžãã¥ãŒãšããŠäœ¿çšãã Hazelcastããªã³ã©ã€ã³ã¹ãã¬ãŒãžãšããŠäœ¿çšããŸãã
ã¹ã±ãŒãªã³ã°
䞊ååŠçãç·šæããã«ã¯ãè€æ°ã®ãã¢ãµãŒããŒã®ã¯ã©ã¹ã¿ãŒãç·šæããŸãã ActiveMQãããŒã«ãŒã¯ãHTTPãããã³ã«çµç±ã§å°çããã¡ãã»ãŒãžãè¿œå ããããã¥ãŒã«ãããããã«ååšããŸãã HTTPãã³ãã«ã¯ãã©ã€ããµãŒããŒå šäœã«ã¡ãã»ãŒãžãé ä¿¡ãããã©ã³ãµãŒã®èåŸã«ãããŸãã
åãµãŒããŒã®å ¥åã¡ãã»ãŒãžãã¥ãŒã¯ã Hazelcastã¯ã©ã¹ã¿ãŒã䜿çšããŠç¶æ ãä¿åããå¿ èŠã«å¿ããŠåŠçãåæããCamelã¢ããªã±ãŒã·ã§ã³ã«ãã£ãŠè§£æãããŸãã ActiveMQãNetworkConnectorsã䜿çšããŠã¯ã©ã¹ã¿ãŒåãããäºãã«ã¡ãã»ãŒãžããå ±æãã§ããŸãã
äžè¬ã«ãã¹ããŒã ã¯æ¬¡ã®ãšããã§ãã

å³ãããããããã«ãã·ã¹ãã ã®ã³ã³ããŒãã³ãã®1ã€ãæ éããŠããèŠçŽ ã®åçæ§ãèæ ®ããŠããã®ããã©ãŒãã³ã¹ã«éåããããšã¯ãããŸããã ããšãã°ãããããã®ãµãŒããŒã®ã¡ãã»ãŒãžãã³ãã©ãŒã§é害ãçºçãããšãActiveMQã¯ãã¥ãŒããä»ã®ãµãŒããŒãžã®ã¡ãã»ãŒãžã®éä¿¡ãéå§ããŸãã ActiveMQãããŒã«ãŒã®1ã€ãã¯ã©ãã·ã¥ãããšããã³ãã©ãŒã¯é£æ¥ãããã®ããããã¯ãããŸãã ãããŠæåŸã«ããµãŒããŒå šäœã«é害ãçºçããå ŽåããµãŒããŒã®æ®ãã®éšåã¯ãäœãèµ·ãããªãã£ããã®ããã«æ±ãæµãç¶ããŸãã ããŒã¿ã®ã»ãã¥ãªãã£ã匷åããããã«ãHazelcastããŒãã¯è¿é£ã®ããŒã¿ã®ããã¯ã¢ããã³ããŒãä¿åããŸãïŒã³ããŒã¯éåæã§äœæãããåããŒãã®çªå·ã¯è¿œå ã§æ§æãããŸãïŒã
ãã®ã¹ããŒã ã«ãããè¿œå ã³ã¹ããªãã§ãµãŒãã¹ãæ¡åŒµãããµãŒããŒãè¿œå ããŠãã³ã³ãã¥ãŒãã£ã³ã°ãªãœãŒã¹ãå¢ããããšãã§ããŸãã
åæ£ã¢ã°ãªã²ãŒã¿ãŒ
éçŽã䜿çšããå ŽåãApache Camelã«ã¯ã éçŽãªããžã㪠ãããã³ã çžé¢ã㌠ãã®æŠå¿µãå«ãŸããŸã ã 1ã€ç®ã¯ãéçŽãããç¶æ ãä¿åããããªããžããªã§ãïŒããšãã°ã1æ¥ãããã®ããããããããã¹ãã®æ°ïŒã 2çªç®ã¯ãç¶æ ããšã«ã¡ãã»ãŒãžãããŒãé åžããããã«äœ¿çšãããããŒã§ãã ã€ãŸããçžé¢ããŒã¯éçŽãªããžããªã®ããŒã§ãïŒããšãã°ãçŸåšã®æ¥ä»ïŒã
åæ§ã®ã¹ããŒã ã®ã¢ã°ãªã²ãŒã¿ãŒã®å ŽåãHazelcastã«ç¶æ ãä¿åããã¯ã©ã¹ã¿ãŒå ã®åäžããŒã®åŠçãåæã§ããç¬èªã®éçŽãªããžããªãå®è£ ããå¿ èŠããããŸããã æ®å¿µãªãããæšæºã®Camelããã±ãŒãžã«ã¯ãã®ãããªå¯èœæ§ã¯ãããŸããã§ããã ãããäœæããå©ç¹ã¯éåžžã«ç°¡åã§ããããšãå€æããŸãã-AggregationRepositoryã€ã³ã¿ãŒãã§ãŒã¹ãå®è£ ããã ãã§ãïŒ
é衚瀺ã®ããã¹ã
public class HazelcastAggregatorRepository implements AggregationRepository { private final Logger logger = LoggerFactory.getLogger(getClass()); // maximum time of waiting for the lock from hz public static final long WAIT_FOR_LOCK_SEC = 20; private final HazelcastInstance hazelcastInstance; private final String repositoryName; private IMap<String, DefaultExchangeHolder> map; public HazelcastAggregatorRepository(HazelcastInstance hazelcastInstance, String repositoryName){ this.hazelcastInstance = hazelcastInstance; this.repositoryName = repositoryName; } @Override protected void doStart() throws Exception { map = hazelcastInstance.getMap(repositoryName); } @Override protected void doStop() throws Exception { /* Nothing to do */ } @Override public Exchange add(CamelContext camelContext, String key, Exchange exchange) { try { DefaultExchangeHolder holder = DefaultExchangeHolder.marshal(exchange); map.tryPut(key, holder, WAIT_FOR_LOCK_SEC, TimeUnit.SECONDS); return toExchange(camelContext, holder); } catch (Exception e) { logger.error("Failed to add new exchange", e); } finally { map.unlock(key); } return null; } @Override public Exchange get(CamelContext camelContext, String key) { try { map.tryLock(key, WAIT_FOR_LOCK_SEC, TimeUnit.SECONDS); return toExchange(camelContext, map.get(key)); } catch (Exception e) { logger.error("Failed to get the exchange", e); } return null; } @Override public void remove(CamelContext camelContext, String key, Exchange exchange) { try { logger.debug("Removing '" + key + "' tryRemove..."); map.tryRemove(key, WAIT_FOR_LOCK_SEC, TimeUnit.SECONDS); } catch (Exception e) { logger.error("Failed to remove the exchange", e); } finally { map.unlock(key); } } @Override public void confirm(CamelContext camelContext, String exchangeId) { /* Nothing to do */ } @Override public Set<String> getKeys() { return Collections.unmodifiableSet(map.keySet()); } private Exchange toExchange(CamelContext camelContext, DefaultExchangeHolder holder) { Exchange exchange = null; if (holder != null) { exchange = new DefaultExchange(camelContext); DefaultExchangeHolder.unmarshal(exchange, holder); } return exchange; } }
ãã®ãããªãªããžããªã䜿çšããã«ã¯ãHazelcastãããžã§ã¯ãã«æ¥ç¶ããŠã³ã³ããã¹ãã§å®£èšããHazelcastã€ã³ã¹ã¿ã³ã¹ãæããªããžããªã®ã»ãããè¿œå ããã ãã§ãã åã¢ã°ãªã²ãŒã¿ãŒã«ã¯ç¬èªã®ããŒã¹ããŒã¹ãå¿ èŠã§ããããããªããžããªã®ååãæå®ããå¿ èŠãããããšã«æ³šæããŠãã ããã Hazelcastèšå®ã§ã¯ãã¯ã©ã¹ã¿ãŒã®äžéšã§ãããã¹ãŠã®ãµãŒããŒãç»é²ããå¿ èŠããããŸãã
ãããã£ãŠãéçŽãè¡ããããµãŒããŒãèæ ®ããããšãªããåæ£ç°å¢ã§ã¢ã°ãªã²ãŒã¿ãŒã䜿çšããæ©äŒãåŸãããŸãã
åæ£ã¿ã€ããŒ
ã¯ã©ã¹ã¿ãŒã«ä¿åãããç¶æ ã®æ°ã¯éåžžã«å€ããªããŸãã ããããããããã¹ãŠãåžžã«å¿ èŠãªããã§ã¯ãããŸããã ããã«ãäžéšã®ç¶æ ïŒããšãã°ãé·æé䜿çšãããŠããªãããã«é·æéã¡ãã»ãŒãžããªãã£ããã¹ãã®ç¶æ ïŒãä¿åããå¿ èŠã¯ãŸã£ãããããŸããã ãã®ãããªç¶æ ãåãé€ããããã«ããã«ã€ããŠä»ã®ã·ã¹ãã ã«éç¥ããããšæããŸãã ãããè¡ãã«ã¯ãæå®ã®é »åºŠã§ã¢ã°ãªã²ãŒã¿ãŒã®é³è åã®ç¶æ ã確èªããããããåé€ããå¿ èŠããããŸãã
ãããè¡ãç°¡åãªæ¹æ³ã¯ãããšãã°Quartzã䜿çšããŠãå®æçãªã¿ã¹ã¯ãè¿œå ããããšã§ãã ããã«ãCamelã䜿çšããŠãããè¡ãããšãã§ããŸãã ãã ããå€ãã®ãã¢ãµãŒããŒãããã¯ã©ã¹ã¿ãŒã§å®è¡ãããããšã«æ³šæããŠãã ããã ãŸããå®æçã«Quartzã¿ã¹ã¯ããã¹ãŠåæã«å®è¡ããããšã¯æãŸãããããŸããã ãããåé¿ããã«ã¯ãHazelcastããã¯ã®å©ããåããŠå床åæãè¡ãã ãã§ååã§ãã ããããQuartzã匷å¶çã«1å°ã®ãµãŒããŒã®ã¿ã§åæåããæ¹æ³ããŸãã¯åæããã©ã®æç¹ã§åæåããã®ã§ãã
Springã䜿çšããŠCamelã³ã³ããã¹ããšã·ã¹ãã ã®ä»ã®ãã¹ãŠã®ã³ã³ããŒãã³ããåæåããQuartzã«ã¯ã©ã¹ã¿ãŒãã1ã€ã®ãµãŒããŒã®ã¿ã§ã¹ã±ãžã¥ãŒã©ãŒã匷å¶çã«èµ·åãããã«ã¯ããŸããã³ã³ããã¹ãã§æ瀺çã«å®£èšããŠèªåèµ·åãç¡å¹ã«ããå¿ èŠããããŸãïŒ
<bean id="quartz" class="org.apache.camel.component.quartz.QuartzComponent"> <property name="autoStartScheduler" value="false"/> </bean>
第äºã«ãããã¯ããã£ããã£ã§ããå Žåã«ã®ã¿ãã©ããã§åæããŠã¹ã±ãžã¥ãŒã©ãèµ·åãããã®ãã£ããã£ã®æ¬¡ã®ç¬éãåŸ ã€å¿ èŠããããŸãïŒããã¯ããã£ããã£ããåã®ãµãŒããŒã倱æããããäœããã®çç±ã§è§£æŸãããå ŽåïŒã ããã¯ãã³ã³ããã¹ãããªã¬ãŒã€ãã³ããåŠçã§ããApplicationListenerãªã©ãããã€ãã®æ¹æ³ã§Springã«å®è£ ã§ããŸãã
<bean class="com.my.hazelcast.HazelcastQuartzSchedulerStartupListener"> <property name="hazelcastInstance" ref="hazelcastInstance"/> <property name="quartzComponent" ref="quartz"/> </bean>
ã¹ã±ãžã¥ãŒã©åæåã¯ã©ã¹ã®æ¬¡ã®å®è£ ãååŸããŸãã
é衚瀺ã®ããã¹ã
public class HazelcastQuartzSchedulerStartupListener implements ShutdownPrepared, ApplicationListener { public static final String DEFAULT_QUARTZ_LOCK = "defaultQuartzLock"; protected volatile boolean initialized = false; Logger log = LoggerFactory.getLogger(getClass()); Lock lock; protected volatile boolean initialized = false; protected String lockName; protected HazelcastInstance hazelcastInstance; protected QuartzComponent quartzComponent; public HazelcastQuartzSchedulerStartupListener() { super(); log.info("HazelcastQuartzSchedulerStartupListener created"); } public void setLockName(final String lockName) { this.lockName = lockName; } public synchronized Lock getLock() { if (lock == null) { lock = hazelcastInstance.getLock(lockName != null ? lockName : DEFAULT_QUARTZ_LOCK); } return lock; } @Override public void prepareShutdown(boolean forced) { unlock(); } @Required public void setQuartzComponent(QuartzComponent quartzComponent) { this.quartzComponent = quartzComponent; } @Required public void setHazelcastInstance(HazelcastInstance hazelcastInstance) { this.hazelcastInstance = hazelcastInstance; } @Override public synchronized void onApplicationEvent(ApplicationEvent event) { if (initialized) { return; } try { while (true) { try { getLock().lock(); log.warn("This node is now the master Quartz!"); try { quartzComponent.startScheduler(); } catch (Exception e) { unlock(); throw new RuntimeException(e); } return; } catch (OperationTimeoutException e) { log.warn("This node is not the master Quartz and failed to wait for the lock!"); } } } catch (Exception e) { log.error("Error while trying to wait for the lock from Hazelcast!", e); } } private synchronized void unlock() { try { getLock().unlock(); } catch (IllegalStateException e) { log.warn("Exception while trying to unlock quartz lock: Hazelcast instance is already inactive!"); } catch (Exception e) { log.warn("Exception during the unlock of the master Quartz!", e); } } }
ãããã£ãŠã Camelãæšå¥šããå®æçãªã¿ã¹ã¯ã䜿çšããåæ£ã©ã³ã¿ã€ã ãèæ ®ããããšãã§ããŸãã ããšãã°ã次ã®ããã«ïŒ
<route id="quartz-route"> <from uri="quartz://quartz-test/test?cron=*+*+*+*+*+?"/> <log message="Quartz each second message caught ${in.body.class}!"/> <to uri="direct:queue:done-quartz"/> </route>
æéç¶æ ãã·ã³
åçŽãªéèšæ¹æ³ïŒããšãã°ãåèšã®ã«ãŠã³ãïŒã«å ããŠãããšãã°ãå®äºãããã¹ãã®çŸåšã®ç¶æ ãåžžã«èšæ¶ããããã«ãçä¿¡ã¡ãã»ãŒãžã«å¿ããŠã¢ã°ãªã²ãŒã¿ãŒã®ç¶æ ãåãæ¿ããå¿ èŠããã°ãã°ãããŸããã ãã®æ©èœãå®è£ ããã«ã¯ã æéç¶æ ãã·ã³ãé©ããŠããŸãã ãã¹ãã®ç¶æ ããããšæ³åããŠãã ããã ããšãã°ãTestPassedStateã ãã®ãã¹ãã®TestFailedã¡ãã»ãŒãžãåãåã£ããšããã¢ã°ãªã²ãŒã¿ãŒã®ç¶æ ãTestFailedStateã«åãæ¿ããTestPassedãåã³TestPassedStateã«åãåã£ããšãã«åãæ¿ããå¿ èŠããããŸãã ç¡éãžãšç¶ããŸãã ãããã®é·ç§»ã«åºã¥ããŠãããšãã°ãé·ç§»ãTestPassed-> TestFailedã§çºçããå Žåããã¹ãŠã®é¢ä¿è ã«ãã¹ããå£ããããšãéç¥ããå¿ èŠããããªã©ãããã€ãã®çµè«ãåŒãåºãããšãã§ããŸãã éã®é·ç§»ãããå Žåã¯ãéã«ããã¹ãŠãé 調ã«ãªã£ãããšãäŒããŸãã

ãã®ãããªéçŽæŠç¥ãå®è£ ããããã®ãªãã·ã§ã³ãéžæãããšãã¡ãã»ãŒãžåŠçã®çŸå®ã«é©åããç¹å®ã®æéç¶æ ãã·ã³ã¢ãã«ãå¿ èŠã§ãããšããçµè«ã«éããŸããã ãŸããã¢ã°ãªã²ãŒã¿ãŒã®å ¥åã§åä¿¡ãããã¡ãã»ãŒãžã¯ç¹å®ã®ãªããžã§ã¯ãã®ã»ããã§ãã åã€ãã³ãã«ã¯ç¬èªã®ã¿ã€ãããããããJavaã®ã¯ã©ã¹ã«ç°¡åã«åé¡ãããŸãã ã€ãã³ãã®ã¿ã€ããèšè¿°ããããã«ãxsd-schemeã䜿çšããŸããxjcã䜿çšããŠãã¯ã©ã¹ã®ã»ãããçæããŸãã ãããã®ã¯ã©ã¹ã¯ãjaxbã䜿çšããŠxmlããã³jsonã§ç°¡åã«ã·ãªã¢ã©ã€ãºããã³ãã·ãªã¢ã©ã€ãºãããŸãã Hazelcastã®ç¶æ ã¯ãxsdã«ãã£ãŠçæãããã¯ã©ã¹ã®ã»ããã§ãè¡šãããŸãã ãããã£ãŠãã¡ãã»ãŒãžã®ã¿ã€ããšçŸåšã®ç¶æ ã®ã¿ã€ãã«åºã¥ããŠãç¶æ éã®é·ç§»ãç°¡åã«åŠçã§ããæéç¶æ ãã·ã³ã®å®è£ ãèŠã€ããå¿ èŠããããŸããã ãŸããå€ãã®åæ§ã®ã©ã€ãã©ãªã®ããã«ããããã®é·ç§»ã宣èšçã«èšå®ããåœä»€çã«ã§ã¯ãªãèšå®ããããšãæãã§ããŸããã ãã®ãããªæ©èœã®è»œéãªå®è£ ã¯èŠã€ãããªãã£ããããããŒãºãèæ ®ããCamelãžã®ã«ãŒãã«æ²¿ã£ãŠéä¿¡ãããã¡ãã»ãŒãžãåŠçããããã®åºç€ãååã«ç¢ºç«ããŠãç¬èªã«äœæããããšã«ããŸããã
ç§ãã¡ã®ããŒãºãå®çŸããå°ããªã©ã€ãã©ãªã¯YatomataãšåŒã°ãïŒYet Another auTomataãšããèšèããïŒã githubã§å ¥æã§ããŸãã
FSMã¢ãã«ãããããåçŽåããããšã決å®ãããŸãã-ããšãã°ãã³ã³ããã¹ãã¯çŸåšã®ç¶æ ã®ãªããžã§ã¯ãã«ãã£ãŠèšå®ãããã¡ãã»ãŒãžã«ã¯ããŒã¿ãä¿åãããŸãã ãã ãããã®å Žåã®é·ç§»ã¯ãç¶æ ãšã¡ãã»ãŒãžã®ã¿ã€ãã«ãã£ãŠã®ã¿æ±ºå®ãããŸãã ã¹ããŒããã·ã³ã¯ãã¢ã°ãªã²ãŒã¿ãŒãšããŠäœ¿çšãããã¯ã©ã¹ã«å¯ŸããŠå®çŸ©ãããŸãã ãããè¡ãã«ã¯ãã¯ã©ã¹ã«@FSM泚éãä»ããŸãã åæç¶æ ïŒéå§ïŒãšäžé£ã®é·ç§»ãå®çŸ©ãããŠããããã®äžéšã¯éçŽãåæ¢ãïŒstop = trueïŒãèç©ãããç¶æ ãã«ãŒãã«æ²¿ã£ãŠããã«èªåçã«éä¿¡ããŸãã
é·ç§»ã®ã»ããã¯@Transitionsã¢ãããŒã·ã§ã³ãš@Transitã¢ãããŒã·ã§ã³ã®é åã«ãã£ãŠå®£èšãããŸããããããã§ãåæç¶æ ã®ã»ããïŒfromïŒãæçµç¶æ ïŒtoïŒããã®é·ç§»ãã¢ã¯ãã£ãåãããã€ãã³ãã®ã»ããïŒonïŒãæå®ã§ããŸãããã·ã³ã®çµããïŒåæ¢ïŒã é·ç§»ãåŠçããããã«ãã¢ãããŒã·ã§ã³@OnTransit ã @BeforeTransit ãããã³@AfterTransitãæäŸãããŠããããããã䜿çšããŠã¯ã©ã¹å ã®ãããªãã¯ã¡ãœãããããŒã¯ã§ããŸãã ãããã®ã¡ãœããã¯ããã®çœ²åã«äžèŽããäžèŽããé·ç§»ãèŠã€ãã£ãå Žåã«åŒã³åºãããŸãã
@FSM(start = Undefined.class) @Transitions({ @Transit(on = TestPassed.class, to = TestPassedState.class), @Transit(on = TestFailed.class, to = TestFailedState.class), @Transit(stop = true, on = TestExpired.class), }) public class TestStateFSM { @OnTransit public void onTestFailed(State oldState, TestFailedState newState, TestFailed event){} @OnTransit public void onTestPassed(State oldState, TestPassedState newState, TestPassed event){} }
ã¹ããŒããã·ã³ã®æäœã¯æ¬¡ã®ãšããã§ãã
Yatomata<TestStateFSM> fsm = new FSMBuilder(TestStateFSM.class).build(); fsm.getCurrentState(); // returns instance of Undefined fsm.isStopped(); // returns false fsm.getFSM(); // returns instance of TestStateFSM fsm.fire(new TestPassed()); // returns instance of TestPassedState fsm.fire(new TestFailed()); // returns instance of TestFailedState fsm.fire(new TestExpired()); // returns instance of TestFailedState fsm.isStopped(); // returns true
AggregationStrategyã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããããšã«ãããFSMAggregationStrategyãäœæããŸãããããã¯ãSpringã®ã³ã³ããã¹ãã§æ¬¡ã®ããã«å®£èšãããŸãã
<bean id="runnableAggregator" class="com.my.FSMAggregationStrategy"> <constructor-arg value="com.my.TestStateFSM"/> </bean>
ãã®ã¹ããŒããã·ã³ã䜿çšããå Žåã®éçŽæŠç¥ã®æãåçŽãªå®è£ ã¯ã次ã®ããã«ãªããŸãã
é衚瀺ã®ããã¹ã
public class FSMAggregationStrategy<T> implements AggregationStrategy { private final Yatomata<T> fsmEngine; public FSMAggregationStrategy(Class fsmClass) { this.fsmEngine = new FSMBuilder(fsmClass).build(); } @Override public Exchange aggregate(Exchange state, Exchange message) { Object result = state == null ? null : state.getIn().getBody(); try { Object event = message.getIn().getBody(); Object fsm = fsmEngine.getFSM(); result = fsmEngine.fire(event); } catch (Exception e) { logger.error(fsm + " error", e); } if (result != null) { message.getIn().setBody(result); } return message; } public boolean isCompleted() { return fsmEngine.isCompleted(); } }
çµè«
ãããã®ææ³ã«ãããããŸããŸãªç®çã§è€æ°ã®æ°Žå¹³æ¹åã«ã¹ã±ãŒã©ãã«ãªãµãŒãã¹ãå®è£ ã§ããŸããã Apache Camelã¯æé«ã®é¢ã瀺ããæåŸ ã«å¿ããŸããã 宣èšæ§ãšé«ãæè»æ§ãçµã¿åããããŠãããæ°ããæ©èœããµããŒãããã³è¿œå ããããã®æå°éã®åŽåã§ãçµ±åã¢ããªã±ãŒã·ã§ã³ã®åªããã¹ã±ãŒãªã³ã°ãå šäœãšããŠæäŸããŸãã