TimerService 抛出 NullPointerException
TimerService throws NullPointerException
我正在尝试编写一项服务,该服务将从远程源收集数据并将其保存到数据库中。但是,它会在服务器启动时抛出 NullPointerException
。
我关注了Oracle's tutorial
这是日志:
java.lang.NullPointerException
at org.eclipse.persistence.platform.server.ServerPlatformUtils.createServerPlatform(ServerPlatformUtils.java:99)
at org.eclipse.persistence.sessions.factories.SessionManager.init(SessionManager.java:77)
at org.eclipse.persistence.sessions.factories.SessionManager.<clinit>(SessionManager.java:71)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.addSessionToGlobalSessionManager(EntityManagerSetupImpl.java:907)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.initSession(EntityManagerSetupImpl.java:2671)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:675)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.getAbstractSession(EntityManagerFactoryDelegate.java:205)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.createEntityManagerImpl(EntityManagerFactoryDelegate.java:305)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:337)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:318)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper._getDelegate(EntityManagerWrapper.java:197)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.createNamedQuery(EntityManagerWrapper.java:521)
at org.glassfish.ejb.persistent.timer.TimerBean.findTimersByOwnerAndState(TimerBean.java:209)
at org.glassfish.ejb.persistent.timer.TimerBean.findActiveTimersOwnedByThisServer(TimerBean.java:523)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4786)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4758)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4746)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
at com.sun.proxy.$Proxy166.findActiveTimersOwnedByThisServer(Unknown Source)
at org.glassfish.ejb.persistent.timer.PersistentEJBTimerService.restoreEJBTimers(PersistentEJBTimerService.java:369)
at org.glassfish.ejb.persistent.timer.PersistentEJBTimerService.resetEJBTimers(PersistentEJBTimerService.java:1400)
at com.sun.ejb.containers.EJBTimerService.initEJBTimerService(EJBTimerService.java:236)
at com.sun.ejb.containers.EJBTimerService.getEJBTimerService(EJBTimerService.java:205)
at com.sun.ejb.containers.EJBTimerService.getEJBTimerService(EJBTimerService.java:187)
at com.sun.ejb.containers.BaseContainer.<init>(BaseContainer.java:825)
at com.sun.ejb.containers.AbstractSingletonContainer.<init>(AbstractSingletonContainer.java:127)
at com.sun.ejb.containers.CMCSingletonContainer.<init>(CMCSingletonContainer.java:76)
at com.sun.ejb.containers.SingletonContainerFactory.createContainer(SingletonContainerFactory.java:68)
at org.glassfish.ejb.startup.EjbApplication.loadContainers(EjbApplication.java:221)
at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:291)
at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:99)
我的代码:
package db;
import sun.net.www.protocol.http.HttpURLConnection;
import javax.annotation.Resource;
import javax.ejb.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
@Singleton
@Startup
public class DataCollector{
@Resource
TimerService timerService;
private DBController db = new DBController();
private static final Logger logger = Logger.getLogger("db.DataCollector");
@Schedule(second = "*/4")
public void collectData(Timer timer){
String URL = "...";
try{
java.net.URL url = new URL(URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream is = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
String [] columns;
while((line = reader.readLine()) != null){
if(line.contains("Err")) {
logger.log(Level.WARNING, "[SENSORS]: {s}", line);
continue;
}
columns = parseData(line);
if(columns.length != 10) {
logger.log(Level.WARNING, "[SENSORS]: BAD DATA");
continue;
}
db.insertToProcessingCollection(columns);
}
} catch (IOException e) {
logger.log(Level.SEVERE, e.getLocalizedMessage());
}
}
private String [] parseData(String data){
return data.split("\t");
}
}
编辑:
DBController.java:
public class DBController {
private MongoDatabase db;
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
private static final Logger logger = Logger.getLogger("db.DBController");
public DBController(){
MongoClient client = new MongoClient();
db = client.getDatabase("master");
}
public boolean insertToProcessingCollection(String [] data){
MongoCollection<Document> collection = db.getCollection("newData");
try {
Document doc = new Document()...
collection.insertOne(doc);
return true;
} catch (ParseException e) {
logger.log(Level.SEVERE, e.getMessage());
return false;
}
}
public void pushDataToHistoryCollection(){
try {
MongoCollection<Document> historyCollection = db.getCollection("oldData");
MongoCollection<Document> processingCollection = db.getCollection("newData");
processingCollection.find().forEach((Block<Document>) historyCollection::insertOne);
processingCollection.deleteMany(new Document());
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage());
}
}
public JSONArray getNewData(){
try {
MongoCollection<Document> collection = db.getCollection("newData");
FindIterable<Document> newData = collection.find();
JSONArray result = convertToJSON(newData);
pushDataToHistoryCollection();
return result;
} catch (Exception e) {
logger.severe(e.getMessage());
return null;
}
}
public JSONArray convertToJSON(FindIterable<Document> data){
JSONArray result = new JSONArray();
data.forEach((Block<Document>) document -> {
JSONObject object = new JSONObject(document.toJson());
object.put("dateTime", dateFormat.format(document.get("dateTime")));
result.put(object);
});
return result;
}
public void removeOldData(){
MongoCollection<Document> collection = db.getCollection("oldData");
collection.deleteMany(new Document());
}
}
因此,经过一番挖掘后,我发现您的应用程序发生的情况已经在其他几个问题上得到了报告。
即使您没有直接使用 EclipseLink,Glassfish 也在 hood 下使用它来建立数据库连接。
报告的问题之一存在于 Glassfish 的 JIRA 上,已在 EclipseLink's 2.6.2 release:
完成修复
此外,我发现 Payara(基于 Glassfish)也有同样的问题:
此外,正如@vempo 所述,报告的问题也与其他两个 SO 问题有关:
作为解决方案,您可以尝试绑定新的(稳定的)版本的 EclipseLink (2.6.2) to your project and deploy it, as @Tiny suggests 。GlassFish 提供的 EclipseLink 版本将替换为与您的应用程序一起打包的版本。
嗯,花了一些时间,但我终于修好了。正如@aribeiro 和@vempo 所述,问题可能与 2.6.2 版本中修复的 EclipseLink 错误有关。但是,在添加 EclipseLink 2.6.2 依赖项后,仍然抛出异常。我决定切换到 WildFly 10 服务器,问题消失了,但服务无论如何都无法启动。
添加了记录服务创建的构造函数并且它有效。
正如@Max Fichtelmann 所说,@Schedule
中的 here minute
和 hour
参数默认等于 0。声明 @Schedule(second = "*/4" , minute="*", hour = "*")
修复了所有问题,它在 WildFly 10.0.0 和 GlassFish 4.1.1
中都有效
我正在尝试编写一项服务,该服务将从远程源收集数据并将其保存到数据库中。但是,它会在服务器启动时抛出 NullPointerException
。
我关注了Oracle's tutorial
这是日志:
java.lang.NullPointerException
at org.eclipse.persistence.platform.server.ServerPlatformUtils.createServerPlatform(ServerPlatformUtils.java:99)
at org.eclipse.persistence.sessions.factories.SessionManager.init(SessionManager.java:77)
at org.eclipse.persistence.sessions.factories.SessionManager.<clinit>(SessionManager.java:71)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.addSessionToGlobalSessionManager(EntityManagerSetupImpl.java:907)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.initSession(EntityManagerSetupImpl.java:2671)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:675)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.getAbstractSession(EntityManagerFactoryDelegate.java:205)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.createEntityManagerImpl(EntityManagerFactoryDelegate.java:305)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:337)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:318)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper._getDelegate(EntityManagerWrapper.java:197)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.createNamedQuery(EntityManagerWrapper.java:521)
at org.glassfish.ejb.persistent.timer.TimerBean.findTimersByOwnerAndState(TimerBean.java:209)
at org.glassfish.ejb.persistent.timer.TimerBean.findActiveTimersOwnedByThisServer(TimerBean.java:523)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4786)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4758)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4746)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
at com.sun.proxy.$Proxy166.findActiveTimersOwnedByThisServer(Unknown Source)
at org.glassfish.ejb.persistent.timer.PersistentEJBTimerService.restoreEJBTimers(PersistentEJBTimerService.java:369)
at org.glassfish.ejb.persistent.timer.PersistentEJBTimerService.resetEJBTimers(PersistentEJBTimerService.java:1400)
at com.sun.ejb.containers.EJBTimerService.initEJBTimerService(EJBTimerService.java:236)
at com.sun.ejb.containers.EJBTimerService.getEJBTimerService(EJBTimerService.java:205)
at com.sun.ejb.containers.EJBTimerService.getEJBTimerService(EJBTimerService.java:187)
at com.sun.ejb.containers.BaseContainer.<init>(BaseContainer.java:825)
at com.sun.ejb.containers.AbstractSingletonContainer.<init>(AbstractSingletonContainer.java:127)
at com.sun.ejb.containers.CMCSingletonContainer.<init>(CMCSingletonContainer.java:76)
at com.sun.ejb.containers.SingletonContainerFactory.createContainer(SingletonContainerFactory.java:68)
at org.glassfish.ejb.startup.EjbApplication.loadContainers(EjbApplication.java:221)
at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:291)
at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:99)
我的代码:
package db;
import sun.net.www.protocol.http.HttpURLConnection;
import javax.annotation.Resource;
import javax.ejb.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
@Singleton
@Startup
public class DataCollector{
@Resource
TimerService timerService;
private DBController db = new DBController();
private static final Logger logger = Logger.getLogger("db.DataCollector");
@Schedule(second = "*/4")
public void collectData(Timer timer){
String URL = "...";
try{
java.net.URL url = new URL(URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream is = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
String [] columns;
while((line = reader.readLine()) != null){
if(line.contains("Err")) {
logger.log(Level.WARNING, "[SENSORS]: {s}", line);
continue;
}
columns = parseData(line);
if(columns.length != 10) {
logger.log(Level.WARNING, "[SENSORS]: BAD DATA");
continue;
}
db.insertToProcessingCollection(columns);
}
} catch (IOException e) {
logger.log(Level.SEVERE, e.getLocalizedMessage());
}
}
private String [] parseData(String data){
return data.split("\t");
}
}
编辑:
DBController.java:
public class DBController {
private MongoDatabase db;
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
private static final Logger logger = Logger.getLogger("db.DBController");
public DBController(){
MongoClient client = new MongoClient();
db = client.getDatabase("master");
}
public boolean insertToProcessingCollection(String [] data){
MongoCollection<Document> collection = db.getCollection("newData");
try {
Document doc = new Document()...
collection.insertOne(doc);
return true;
} catch (ParseException e) {
logger.log(Level.SEVERE, e.getMessage());
return false;
}
}
public void pushDataToHistoryCollection(){
try {
MongoCollection<Document> historyCollection = db.getCollection("oldData");
MongoCollection<Document> processingCollection = db.getCollection("newData");
processingCollection.find().forEach((Block<Document>) historyCollection::insertOne);
processingCollection.deleteMany(new Document());
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage());
}
}
public JSONArray getNewData(){
try {
MongoCollection<Document> collection = db.getCollection("newData");
FindIterable<Document> newData = collection.find();
JSONArray result = convertToJSON(newData);
pushDataToHistoryCollection();
return result;
} catch (Exception e) {
logger.severe(e.getMessage());
return null;
}
}
public JSONArray convertToJSON(FindIterable<Document> data){
JSONArray result = new JSONArray();
data.forEach((Block<Document>) document -> {
JSONObject object = new JSONObject(document.toJson());
object.put("dateTime", dateFormat.format(document.get("dateTime")));
result.put(object);
});
return result;
}
public void removeOldData(){
MongoCollection<Document> collection = db.getCollection("oldData");
collection.deleteMany(new Document());
}
}
因此,经过一番挖掘后,我发现您的应用程序发生的情况已经在其他几个问题上得到了报告。
即使您没有直接使用 EclipseLink,Glassfish 也在 hood 下使用它来建立数据库连接。
报告的问题之一存在于 Glassfish 的 JIRA 上,已在 EclipseLink's 2.6.2 release:
完成修复此外,我发现 Payara(基于 Glassfish)也有同样的问题:
此外,正如@vempo 所述,报告的问题也与其他两个 SO 问题有关:
作为解决方案,您可以尝试绑定新的(稳定的)版本的 EclipseLink (2.6.2) to your project and deploy it, as @Tiny suggests
嗯,花了一些时间,但我终于修好了。正如@aribeiro 和@vempo 所述,问题可能与 2.6.2 版本中修复的 EclipseLink 错误有关。但是,在添加 EclipseLink 2.6.2 依赖项后,仍然抛出异常。我决定切换到 WildFly 10 服务器,问题消失了,但服务无论如何都无法启动。 添加了记录服务创建的构造函数并且它有效。
正如@Max Fichtelmann 所说,@Schedule
中的 here minute
和 hour
参数默认等于 0。声明 @Schedule(second = "*/4" , minute="*", hour = "*")
修复了所有问题,它在 WildFly 10.0.0 和 GlassFish 4.1.1