Reputation: 908
I'm trying to write a service that will collect data from a remote source and save it to the DB. However, it throws a NullPointerException
on server startup.
I followed Oracle's tutorial
Here's the log:
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)
And my code:
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");
}
}
EDIT:
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());
}
}
Upvotes: 0
Views: 1846
Reputation: 908
Well, it took some time but I have finally fixed it. As @aribeiro and @vempo stated the problem might have been related to EclipseLink bug fixed in 2.6.2 version. However, after adding EclipseLink 2.6.2 dependency the exception was still thrown. I decided to switch to WildFly 10 server and the issue was gone but the Service wouldn't start anyway. Added constructor that logged the creation of the service and it worked.
As @Max Fichtelmann said here minute
and hour
parameters in @Schedule
are equal 0 by default. Declaring @Schedule(second = "*/4" , minute="*", hour = "*")
fixed everything and it worked both in WildFly 10.0.0 and GlassFish 4.1.1
Upvotes: 1
Reputation: 4202
So, after some digging I found out that what's happening with your application was already reported on several other issues.
Even though you're not using EclipseLink directly, Glassfish is using it under the hood to establish database connections.
One of the reported issues is present on Glassfish's JIRA, with fix being done at EclipseLink's 2.6.2 release:
Also, I've found out that Payara (which is based on Glassfish) has the same problem:
Furthermore, as @vempo stated, the problem reported is also related with these other two SO questions:
As solution, you could try binding the new (stable) version of EclipseLink (2.6.2) to your project and deploy it, as @Tiny suggests here. The version of EclipseLink, supplied by GlassFish, will replaced by the one packed with your application.
Upvotes: 1