2013-04-07 73 views
5

Làm thế nào bạn sẽ đề nghị để thực hiện những điều sau đây trong JavaEE:Làm thế nào để thực hiện một quá trình liên tục chạy trong JavaEE

  1. tôi cần phải có một quá trình nền trong máy chủ ứng dụng (Tôi đã suy nghĩ một session bean trạng thái) liên tục theo dõi "cái gì đó" và nếu một số điều kiện áp dụng nó sẽ hoạt động với cơ sở dữ liệu.

  2. Quan trọng nhất là phải thao tác từ xa bởi nhiều khách hàng khác nhau.

Vì vậy, về cơ bản, tôi cần một quy trình sẽ chạy liên tục, giữ trạng thái của nó và mở cho các lời gọi phương thức của một số khách hàng ở xa.

Vì tôi mới dùng JavaEE, tôi hơi bối rối khi tiếp cận/"công nghệ" để sử dụng. Một trợ giúp sẽ được đánh giá cao.

Trả lời

6

Bạn có thể sử dụng kết hợp phiên không quốc tịch hoặc đậu đơn với bộ hẹn giờ EJB một dịch vụ hẹn giờ. Các bean sẽ giao diện được sử dụng bởi các khách hàng từ xa để kiểm soát quá trình nền. Dịch vụ hẹn giờ sẽ định kỳ gọi lại một phương thức trên bean để xác minh điều kiện. Bộ định thời được tự động lưu giữ bởi vùng chứa EJB, vì vậy chúng sẽ thực hiện công việc của họ khi các máy khách bean của bạn bị ngắt kết nối.

Đây là một phác thảo:

@Singleton 
... 
public TimerMangerbean implements TimerManager { 

    @Resource 
    private TimerService timerService; 

    public void startMonitoring() { 
     //start in 5 sec and timeout every 10 minutes 
     Timer timer = timerService.createTimer(5000, 60000, "MyTimer"); 
    } 

    public void stopMonitoring() { 
     Collection<Timer> timers = timerService.getTimers(); 
     for(Timer timer : timers) { 
     //look for your timer 
     if("MyTimer".equals(timer.getInfo())) { 
      timer.cancel();break; 
     } 
     } 
    } 

    //called every 10 minutes 
    @Timeout 
    public void onTimeout() { 
     //verify the condition and do your processing 
    } 
} 

Xem thêm: Using the timer service on Oracle JavaEE tutorial

+0

Đánh giá cao câu trả lời của bạn, nhưng tôi đã hy vọng một cách cơ bản hơn để thực hiện nó, giải pháp bạn đề xuất trông giống như một mẹo. Có một giải pháp cơ bản nào khác, phù hợp với một phạm vi rộng hơn của các vấn đề của các quy trình liên tục và thao tác của chúng. –

+0

Không, không phải là một thủ thuật, 'TimerService' và' Timer' (s) là cách tiêu chuẩn trong JEE để kiểm soát và thực thi các tiến trình lặp đi lặp lại. Họ không buộc bạn vào một loại vấn đề cụ thể. Bạn thấy những giới hạn nào trong cách tiếp cận này? Như bạn đã nói câu hỏi có vẻ là một trận đấu hoàn hảo. – dcernahoschi

+0

+1 Không có hỗ trợ trực tiếp cho các quy trình nền dài chạy trong Java EE. Thay vào đó, chúng có các bộ định thời hỗ trợ định kỳ, với 'TimerService'. – ewernli

1

Java EE là giải pháp. Bạn sẽ cần phải làm theo các bước thoses:

  1. xây dựng một ứng dụng Java EE, một lọ chứa EJB:

    1.1 bạn sẽ cần một IDE: Eclipse Juno là favorit của tôi, 1.2 Nhiều tuto tồn tại trên Trang web. Tìm kiếm EJB3 và bạn sẽ tìm thấy,

  2. có một máy chủ ứng dụng để chạy EJB của bạn. JBoss là một lựa chọn tốt, Glassfish là một lựa chọn tốt khác. Với JBoss và plugin JBoss Tools cho Eclipse được cài đặt, bạn sẽ có thể xây dựng và chạy nhanh một ứng dụng cơ bản.

EDIT: một lớp Timer EJB đầy đủ (với tải lại tự động nếu cần thiết)

package clouderial.saas.commons.utils; 

import java.util.Map; 

import javax.annotation.PreDestroy; 
import javax.annotation.Resource; 
import javax.ejb.ScheduleExpression; 
import javax.ejb.Timeout; 
import javax.ejb.Timer; 
import javax.ejb.TimerConfig; 
import javax.ejb.TimerService; 
import javax.inject.Inject; 

import jmcnet.libcommun.exception.ExceptionTechnique; 
import jmcnet.libcommun.utilit.mail.MailException; 

import org.apache.commons.configuration.event.ConfigurationEvent; 
import org.apache.commons.configuration.event.ConfigurationListener; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import clouderial.saas.commons.email.EmailSender; 
import clouderial.saas.commons.jpamongo.JPAMongoBasePersistenceContextAccessor; 

/** 
* A base class for a periodic process 
* @author jmc 
* 
*/ 
public abstract class PeriodicProcessBase extends JPAMongoBasePersistenceContextAccessor implements ConfigurationListener { 
    private static Logger log = LoggerFactory.getLogger(PeriodicProcessBase.class); 

    @Resource 
    private TimerService timerService; 

    @Inject 
    protected GlobalConfiguration _config; 

    @Inject 
    protected EmailSender _emailSender; 

    private Timer _timer=null; 

    private String _processName=null; 
    private Logger _log = null; 

    protected void initTimer(String processName, Logger log) { 
     if (processName != null) _processName = processName; 
     if (log != null) _log = log; 

     String second = _config.getString("timer."+_processName+".second","0"); 
     String minute = _config.getString("timer."+_processName+".minute","0"); 
     String hour  = _config.getString("timer."+_processName+".hours","4"); 
     String dayOfWeek = _config.getString("timer."+_processName+".dayOfWeek","*"); 

     ScheduleExpression scheduleExp = 
       new ScheduleExpression().second(second).minute(minute).hour(hour).dayOfWeek(dayOfWeek); 

     cancelTimer(); 
     if (timerService != null) { 
      _timer = timerService.createCalendarTimer(scheduleExp, new TimerConfig(_processName, false)); 
      _log.info("{} : timer programmed for '{}'h, '{}'m, '{}'s for days '{}'.", _processName, hour, minute, second, dayOfWeek); 
     } 
     else _log.error("{} : no timer programmed because timerService is not initialized. (Normal during tests)", _processName); 

     // Listen to change 
     _config.addModificationListener(this); // on timer modification, configurationChanged is called 
    } 

    @PreDestroy 
    private void cancelTimer() { 
     if (_log != null) _log.info("Stopping timer for '{}'", _processName); 
     if (_timer != null) _timer.cancel(); 
     _timer = null; 
    } 

    @Override 
    public void configurationChanged(ConfigurationEvent event) { 
     if (_log != null) _log.info("Configuration have change. Reloading config for ProcessBilling."); 
     _config.removeModificationListener(this); 
     initTimer(null, null); 
    } 

    @Timeout 
    private void run(Timer timer) { 
     runProcess(timer); 
    } 

    /** 
    * The entry point for runner the process. Must be overriden by super class 
    * @param timer 
    */ 
    protected abstract void runProcess(Timer timer); // do the job here 

} 

Tôi hy vọng điều này sẽ giúp.

+0

Vâng, tôi thực sự chạy JBoss 7.1.1 và Eclipse Juno với các công cụ JBoss. Câu hỏi đặt ra là API cụ thể để sử dụng sao cho quy trình được chạy liên tục và, ví dụ, không bị phá hủy khi máy khách đã ngắt kết nối (SLSB). –

+0

OK cho phép kiểm tra phản hồi hoàn chỉnh ở trên để thực hiện TimerEJB trong JBoss 7.1.1 – jmcollin92

1

Như bạn nói cho mình, bạn có hai yêu cầu: 1) theo định kỳ thực hiện một số công việc nền, và 2) đáp ứng yêu cầu khách hàng.

Đối với 1), bạn có thể sử dụng TimerService hoặc sinh ra một chuỗi với ServletContextListener. Thứ hai là không hoàn toàn phù hợp, nhưng hoạt động.Nếu bạn sử dụng tính giờ, bạn có thể tạo một bộ đếm thời gian định kỳ (như được chỉ ra bởi @dcernahoschi), hoặc một bộ đếm thời gian độc đáo mà reschedules bản thân:

@Timeout 
public void onTimeout() { 
    //do something 
    // create a new timer 
} 

Nếu cháy timer định kỳ mỗi 10 giây và bạn phải xử lý kéo dài hình thành hơn 10 giây, bạn có thể gặp sự cố. Có một bộ đếm thời gian sắp xếp lại chính nó hoạt động tốt hơn nếu thời gian xử lý không cố định.

Đối với 2), bạn có thể đi với các trạng thái không chính thức hoặc EJB nghiêm ngặt, đó chính xác là mục đích của chúng.