Quartz预定作业无法访问Websphere中的数据源

时间:2016-06-17 00:10:23

标签: datasource quartz-scheduler websphere-8

我正在开发一个Web应用程序,其中批处理程序需要运行特定时间。我使用Quartz库来安排工作。 Web应用程序部署在Websphere 8.5.5上并且工作正常,通过数据源访问表(代码中给出的数据源是 java:comp / env / jdbc / db_datasource )。这项工作也是在上述时间触发的。

当计划作业通过数据源建立数据库连接时出错,错误是:

javax.naming.ConfigurationException: A JNDI operation on a "java:" name cannot be completed because the server runtime is not able to associate the operation's thread with any J2EE application component.  This condition can occur when the JNDI client using the "java:" name is not executed on the thread of a server application request.  Make sure that a J2EE application does not execute JNDI operations on "java:" names within static code blocks or in threads created by that J2EE application.  Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on "java:" names. [Root exception is javax.naming.NameNotFoundException: Name comp/env/jdbc not found in context "java:".]
at com.ibm.ws.naming.java.javaURLContextImpl.throwExceptionIfDefaultJavaNS(javaURLContextImpl.java:522)
at com.ibm.ws.naming.java.javaURLContextImpl.throwConfigurationExceptionWithDefaultJavaNS(javaURLContextImpl.java:552)
at com.ibm.ws.naming.java.javaURLContextImpl.lookupExt(javaURLContextImpl.java:481)
at com.ibm.ws.naming.java.javaURLContextRoot.lookupExt(javaURLContextRoot.java:485)
at com.ibm.ws.naming.java.javaURLContextRoot.lookup(javaURLContextRoot.java:370)

我从错误消息中了解到,作业是在J2ee容器外部运行的,因此数据源不可用于Job进行连接,我不能同意,因为Quartz是作为ServletContextListener实现的,同样是在web.xml中提到。

Web.xml中

<listener>
    <listener-class>com.ehacampaign.helper.EHAJobSchedulerListener</listener-class>
</listener>

EHAJobSchedulerListener.java

public class EHAJobSchedulerListener implements ServletContextListener {..}

正如您所看到的那样,该类已在Web中注册,我不明白为什么它不能在J2EE容器中使用数据源。

问题是:

  1. 为什么servlet注册的类无法访问J2EE中的数据源 容器
  2. 如果容器中的数据源无法使用,那么如何制作一个 执行作业时与DB的连接?
  3. 注意:我在JBoss AS 7.1中具有相同的设置,并且作业正在顺利运行,访问JBoss AS 7.1中配置的数据源。我必须根据客户的要求在Websphere中开发它。

    已更新

    我附上了修改过的quartz属性文件。即使在添加了workmanagetraread之后,我也遇到了同样的错误。

    org.quartz.threadPool.threadCount=1
    org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
    
    org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
    org.quartz.threadExecutor.class=org.quartz.commonj.WorkManagerThreadExecutor
    org.quartz.threadExecutor.workManagerName=wm/default
    

2 个答案:

答案 0 :(得分:1)

为了在WebSpehre中执行JNDI查找,您的代码必须在托管线程上运行。为了让Quartz在WebSphere的托管线程之一上运行,您必须在quartz.properties中设置以下2个属性(如评论中提到的Alasdair):

org.quartz.threadExecutor.class=org.quartz.commonj.WorkManagerThreadExecutor
org.quartz.threadExecutor.workManagerName=wm/default

org.quartz.threadExecutor.workManagerName的名称可以是您在WebSphere中配置的任何工作管理器的JNDI名称。我建议您只使用wm/default,因为默认情况下它位于您的配置中。

答案 1 :(得分:0)

在aguibert和Alasdair以及reference from here提供的所有帮助下,我能够解决问题。

Quartz属性文件是:

org.quartz.threadPool.threadCount=1
org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
org.quartz.threadExecutor.class=org.quartz.commonj.WorkManagerThreadExecutor
org.quartz.threadExecutor.workManagerName=wm/default

数据库连接或JNDI查找应该在JOB Implemented类的空构造函数中进行。例如,

public class ContractIdFromPartyServiceJob implements Job {

private DataSource ds;

public ContractIdFromPartyServiceJob() {
    try {
        Logger.info("Gets the data source");
        Context context = new InitialContext();
        ds = (DataSource) context.lookup(ApplicationConstants.RESOURCE_REFERENCE_JDBC);
    } catch (RException e) {
        e.printStackTrace();
    }
}

@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException
{
    EHAMarsDAO marsDao = new EHAMarsDAO();
    Connection con = getConnection();
    try {
      marsDao.callDBMethod(con);
    } finally {
      con.close();
    }
 }

public Connection getConnection() throws RACVException
{
    Connection con = null;

    try {
        con = ds.getConnection();
        con.setAutoCommit(false);
        con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
    } catch (SQLException e) {
        throw new RException(Constants.ERROR_CODE_002, Constants.E012_DB_CONNECTION_ERROR, e);
    }
    return con;
}
}