我在JBoss 7.1上开发了一个应用程序,它必须监视fileSystem的一个目录。为此,我编写了一些代码,与我在这篇文章中找到的代码类似:EJB 3.1 and NIO2: Monitoring the file system。因此,我编写了一个带有异步方法的会话EJB,监视我必须监视的路径,以及一个调用会话PollingServiceImpl的@StartUp ejb。下面是我的PollingService代码:
@Stateless
public class PollingServiceImpl {
private Path fichiersXmlPath=Paths.get("/media/sf_DossierPartage/IsidoreJaxb/specXML/fichiersXml");
/**
* Default constructor.
*/
public PollingServiceImpl() {
// TODO Auto-generated constructor stub
}
@Asynchronous
public void pollForXmlMessage() {
WatchService service=null;
// Vérification que le path est un répertoire
try {
Boolean isFolder = (Boolean) Files.getAttribute(fichiersXmlPath,
"basic:isDirectory", LinkOption.NOFOLLOW_LINKS);
if (!isFolder) {
throw new IllegalArgumentException("le path : " + fichiersXmlPath + " n'est pas un répertoire");
}
} catch (IOException ioe) {
System.out.println("le path : " + fichiersXmlPath + " n'est pas un répertoire");
}
System.out.println("Répertoire observé: " + fichiersXmlPath);
// On obtient le système de fichier du chemin
FileSystem fs = fichiersXmlPath.getFileSystem ();
// We create the new WatchService using the new try() block
try{ service = fs.newWatchService();
//On enregistre le chemin dans le watcher
// On surveille les opérations de création
fichiersXmlPath.register(service, StandardWatchEventKinds.ENTRY_CREATE);
// Beginning of the infinite loop
for(;;) {
WatchKey key = service.take();
// Sortir les événements de la queue
Kind<?> kind = null;
for(WatchEvent<?> watchEvent : key.pollEvents()) {
// on teste le type de l'événement
kind = watchEvent.kind();
// If les événements sont perdus
if (StandardWatchEventKinds.OVERFLOW == kind) {
continue; //loop
// Si c'est un événement de création
} else if (StandardWatchEventKinds.ENTRY_CREATE == kind) {
// A new Path was created
Path newPath = ((WatchEvent<Path>) watchEvent).context();
// Output
System.out.println("nouveau chemin : " + newPath +" numKey "+key.toString() );
// buisness process
}
}
if (key != null) {
boolean valid = key.reset();
if (!valid) break; // If the key is no longer valid, the directory is inaccessible so exit the loop.
}
}
} catch(IOException ioe) {
ioe.printStackTrace();
} catch(InterruptedException ie) {
ie.printStackTrace();
} finally{
try {
service.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}下面是startp ejb的代码:@Singleton @Startup public class Initialiser {
@EJB
private PollingServiceImpl pollingService;
public enum States {BEFORESTARTED, STARTED, PAUSED, SHUTTINGDOWN};
private States state;
@PostConstruct
public void initialize() {
state = States.BEFORESTARTED;
pollingService.pollForXmlMessage();
state = States.STARTED;
System.out.println("ETAT : "+state.toString());
}
@PreDestroy
public void terminate() {
state = States.SHUTTINGDOWN;
System.out.println("Shut down in progress");
}
public States getState() {
return state;
}
public void setState(States state) {
this.state = state;
}
}一切看起来都很好,观察器运行良好,但是我有两个问题: 1)一些警告出现在控制台上,如下所示:com.arjuna.ats.arjuna ARJUNA012095: Abort of action id 0:ffff7f000101:-51121f7e:53b7f879:9当其中有多个线程处于活动状态时被调用。15:12:14,522警告com.arjuna.ats.arjuna ARJUNA012108:
CheckedAction::check - atomic action 0:ffff7f000101:-51121f7e:53b7f879:9 aborting with 1 threads active! 15:12:14,522 WARN [com.arjuna.ats.arjuna] (Transaction Reaper Worker 0) ARJUNA012121: TransactionReaper::doCancellations worker Thread[Transaction Reaper Worker 0,5,main] successfully canceled TX 0:ffff7f000101:-51121f7e:53b7f879:9 2)服务器拒绝关闭:显然在启动时启动的线程不会停止。我在一些文章中读到,我必须在Initializer ejb的@PreDestroy方法中停止方法pollForXmlMessage,但我不知道如何才能做到这一点,或者是否有其他解决方案。
有人能帮帮我吗?
发布于 2015-04-07 14:29:09
以下是解决方案的模板:
public class Service{
private volotile boolean isCancelled = false;
public void startService()
{ //infinit loop:
while(!isCancelled) {}
}
public void stopService()
{
isCancelled = true;
}
}
@Singleton
@Startup
public class ServiceStarter{
Service service;
@EJB ServiceAsyncWorker asyncWorker;
@PostConstruct
private void init()
{
service = new Service(...);
asyncWorker.startService(service);
}
@PreDestroy
private void destroy()
{
service.stopService();
}
}
@Singleton
public class ServiceAsyncWorker{
@Asynchronous
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void startService(Service service){
service.startService();
}
}发布于 2014-07-06 06:02:42
每个EJB方法都在事务上下文中执行。如果您的方法从未返回,JBoss会通知您可能挂起了一个非常长的事务。
相反,我建议将其移动到资源适配器中,该适配器在新文件等事件上调用MDB。http://robertpanzer.github.io/blog/2014/inboundra-nointfmdbs.html显示了一个使用JavaEE7风格的MDB的示例,但是将其向下移植到JavaEE 6和JBoss 7应该是微不足道的。
https://stackoverflow.com/questions/24586957
复制相似问题