I simply start up a zookeeper server (3.4.6) with using the org.apache.zookeeper.server.ZooKeeperServerMain.runFromConfig(ServerConfig) method, then I try to shut it down. During shutdown I get this:
11:43:11,176 WARN {main} [org.apache.zookeeper.jmx.MBeanRegistry] Failed to unregister MBean InMemoryDataTree
11:43:11,176 WARN {main} [org.apache.zookeeper.jmx.MBeanRegistry] Error during unregister
javax.management.InstanceNotFoundException: org.apache.ZooKeeperService:name0=StandaloneServer_port-1,name1=InMemoryDataTree
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1095)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.exclusiveUnregisterMBean(DefaultMBeanServerInterceptor.java:427)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.unregisterMBean(DefaultMBeanServerInterceptor.java:415)
at com.sun.jmx.mbeanserver.JmxMBeanServer.unregisterMBean(JmxMBeanServer.java:546)
at org.apache.zookeeper.jmx.MBeanRegistry.unregister(MBeanRegistry.java:115)
at org.apache.zookeeper.jmx.MBeanRegistry.unregister(MBeanRegistry.java:132)
at org.apache.zookeeper.server.ZooKeeperServer.unregisterJMX(ZooKeeperServer.java:465)
at org.apache.zookeeper.server.ZooKeeperServer.shutdown(ZooKeeperServer.java:458)
at org.apache.zookeeper.server.NIOServerCnxnFactory.shutdown(NIOServerCnxnFactory.java:271)
at org.apache.zookeeper.server.ZooKeeperServerMain.shutdown(ZooKeeperServerMain.java:132)
...
I have unfortunately no idea what the error Failed to unregister MBean InMemoryDataTree means. I did not find anything with search engines apart from logs from some project builds. I could read the code, but it would take obviously a lot of time to understand that.
Do I have to change something in my startup process to get rid of this, or is this completely normal?
The logs indicate that it is a warning, and from looking into the source and comments, can largely be ignored. In my experience I do not recall seeing those particular messages, but kept running into run time exceptions/errors that kept subsequent unit tests from running and caused my gradle build to exit the test task without generating the report.
I have no idea how you were trying to shut down ZookeeperServerMain, but my work around was to extend ZookeeperServerMain so I could access its protected shutdown method.
public class MyZookeeperServerMain extends ZookeeperServerMain{
...
public void openZoo() {
/**/
Properties startupProperties = createProperties(DEFAULT_LOG_DIR, 2181);
QuorumPeerConfig quorumConfiguration = new QuorumPeerConfig();
try {
quorumConfiguration.parseProperties(startupProperties);
} catch (Exception e) {
throw new RuntimeException(e);
}
zooKeeperServer = new MyZookeeperServerMain();
final ServerConfig configuration = new ServerConfig();
configuration.readFrom(quorumConfiguration);
zooEntrance = new Thread() {
public void run() {
try {
zooKeeperServer.runFromConfig(configuration);
}
catch (IOException e) {
LOG.error("ZooKeeper Failed", e);
}
catch(Exception ie)
{
LOG.debug("shutting down zookeeper", ie);
}
catch(Error e)
{
System.out.println("error stopping zooKeeper: " + e);
}
}
};
zooEntrance.start();
}
public void closeZoo() {
zooKeeperServer.shutdown();
}
}
Related
I have created java pub/sub consumer relying on the following pub/sub doc.
public static void main(String... args) throws Exception {
TopicName topic = TopicName.create(pubSubProjectName, pubSubTopic);
SubscriptionName subscription = SubscriptionName.create(pubSubProjectName, "ssvp-sub");
SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create();
subscriptionAdminClient.createSubscription(subscription, topic, PushConfig.getDefaultInstance(), 0);
MessageReceiver receiver =
new MessageReceiver() {
#Override
public void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) {
System.out.println("Got message: " + message.getData().toStringUtf8());
consumer.ack();
}
};
Subscriber subscriber = null;
try {
subscriber = Subscriber.defaultBuilder(subscription, receiver).build();
subscriber.addListener(
new Subscriber.Listener() {
#Override
public void failed(Subscriber.State from, Throwable failure) {
// Handle failure. This is called when the Subscriber encountered a fatal error and is shutting down.
System.err.println(failure);
}
},
MoreExecutors.directExecutor());
subscriber.startAsync().awaitRunning();
Thread.sleep(60000);
} finally {
if (subscriber != null) {
subscriber.stopAsync();
}
}
}
It works well, but every run it ask for a new subscriber name by throwing StatusRuntimeException exception.
io.grpc.StatusRuntimeException: ALREADY_EXISTS: Resource already exists in the project (resource=ssvp-sub).
(see SubscriptionName.create(pubSubProjectName, "ssvp-sub") line in my code snippet)
I found out that in node.js client we can pass "reuseExisting:true" option to reuse existing subscription :
topic.subscribe('maybe-subscription-name', { reuseExisting: true }, function(err, subscription) {
// subscription was "get-or-create"-ed
});
What option should I pass if I use official java pubsub client?:
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-pubsub</artifactId>
<version>0.13.0-alpha</version>
</dependency>
The Java library does not have a method to allow one to call createSubscription with an existing subscription and not have an exception thrown. You have a couple of options, both of which involve using a try/catch block. The choice depends on whether or not you want to be optimistic about the existence of the subscription.
Pessimistic call:
try {
subscriptionAdminClient.createSubscription(subscription,
topic,
PushConfig.getDefaultInstance(),
0);
} catch (ApiException e) {
if (e.getStatusCode() != Status.Code.ALREADY_EXISTS) {
throw e;
}
}
// You know the subscription exists and can create a Subscriber.
Optimistic call:
try {
subscriptionAdminClient.getSubscripton(subscription);
} catch (ApiException e) {
if (e.getStatusCode() == Status.Code.NOT_FOUND) {
// Create the subscription
} else {
throw e;
}
}
// You know the subscription exists and can create a Subscriber.
In general, it is often the case that one would create the subscription prior to starting up the subscriber itself (via the Cloud Console or gcloud CLI), so you might even want to do the getSubscription() call and throw an exception no matter what. If a subscription got deleted, you might want to draw attention to this case and handle it explicitly as it has implications (like the fact that messages are no longer being stored to be delivered to the subscription).
However, if you are doing something like building a cache server that just needs to get updates transiently while it is up and running, then creating the subscription on startup could make sense.
I have been trying to get a Windows service running from my JAR file. WinRun4j seems to be able to do the job, but I can't get it to work. I am especially finding it quite difficult to debug. I tried several methods for logging (writing to a .txt file, WinRun4j's EventLog class) but I can't seem to generate any output.
The service installs fine (eventually..) and I can start it. It should start a Jetty server that generates an XML file that can be reached over HTTP. The app works for a stand-alone version, just not for the service. The service is started, but as soon as I call the URL it stops without generating an error.
This is my Service class:
package com.some.package;
import org.boris.winrun4j.AbstractService;
import org.boris.winrun4j.ServiceException;
/**
* A basic service.
*/
public class StockService extends AbstractService {
private StockServer srv;
public int serviceMain(String[] args) throws ServiceException {
while (!shutdown) {
try {
Thread.sleep(5000);
} catch(InterruptedException e) {
}
if(srv == null) {
try {
srv = new StockServer();
srv.start();
} catch (Exception e) {
}
}
}
return 0;
}
}
I found out that the service didn't want to start if I started the Jetty server from the serviceMain class. I had to start a new thread. So StockServer extends Thread:
public class StockServer extends Thread {
private Server server;
public void run() {
if (server == null) {
try {
server = new Server(8080);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/example");
StockServlet stockServlet = new StockServlet();
context.addServlet(new ServletHolder(stockServlet), "/stock/*");
server.setHandler(context);
server.setStopAtShutdown(true);
server.start();
server.join();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
Since it runs perfectly fine as Java application I just don't know how to get this thing debugged. I hope one of you can point me in the right direction :).
I ended up using the Java Service Wrapper (JSW). This seemed a lot more complex but ended up to be quite easy. It also provides logging by default so I could easily fix the errors. The JSW had problems finding the correct JDK, since JSW is 32bit and I installed JDK1.7 64 bit (and 1.6 32bit). Installing JDK1.7 32bit fixed it. That might have been the problem with WinRun4j as well, but that is something I will never know :).
Do you know any way to and log all exceptions that are ever thrown (whether catched and handled or not) in java?
Here is my issue: There is an application, that I cannot change, and sometimes it has issues creating a lockfile (relevant code below). When it calls the tryLock() method , freezes for 30 seconds (despite the fact that tryLock is nonblocking), and returns with failure (CANT_CREATE_LOCK). As you see, all the catch tiers mask away the real problem, without even logging it.
final File lockFile = new File(fooHomeDir, ".foo-home.lock");
try
{
FileOutputStream stream = new FileOutputStream(lockFile);
try
{
if (stream.getChannel().tryLock() == null)
{
return LockResult.HELD_BY_OTHERS;
}
this.fileOutputStream = stream;
this.lockFile = lockFile;
return LockResult.OK;
}
catch (OverlappingFileLockException overlappingFileLockException)
{
return LockResult.HELD_BY_OTHERS;
}
catch (IOException ie)
{
return LockResult.CANT_CREATE_LOCK;
}
}
catch (FileNotFoundException fnfe)
{
return LockResult.CANT_CREATE_LOCK;
}
What I wish: Able to see what was the details of the exceptions.
Other info:
The environment is Linux, Java 1.7, Tomcat 7.
The fooHomeDir points to an NFS-backed mount point.
The fooHomeDir's permissions did not change.
The fooHomeDir's owner did not change.
The fooHomeDir's filesystem is not full.
There is no SELinux, or other thing that may interfere.
Basically, it worked before, and stopped "suddenly" and "without cause". So right now I'm investigating.
I'm commencing a remote debug of the application, but until then, suggestions are welcome :-)
Thanks,
joe
UPDATE
For the record, the root cause of the issue was that the rpc.statd daemon died.
Hence, the native locking mechanism failed over NFS.
The symptom was an IOException with the message: "No locks available".
Kudos to Hans Maes
You could create your own implementation of Exception, which will log every error created. And then add it to the classpath with the -Xbootclasspath:bootclasspath flag. I wouldn't recommend it as a 'best practice' but at least you can find the source of your problem.
A very quick example (with room for improvement)
package java.lang;
public class Exception extends Throwable {
public Exception() {
super();
String exception = "Exception";
logWithStack(exception);
}
public Exception(String message) {
super(message);
logWithStack(message);
}
public Exception(String message, Throwable cause) {
super(message, cause);
logWithStack(message);
}
public Exception(Throwable cause) {
super(cause);
logWithStack(cause.getMessage());
}
protected Exception(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
logWithStack(message);
}
private void logWithStack(String exception) {
System.out.println(exception);
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
}
}
Compile to a class file and then add -Xbootclasspath:/directoryWhereClassFileIsLocated/ to the tomcat options.
This is related to these 2 posts:
What is the proper way to close H2?
Tomcat doesn't stop. How can I debug this?
Basically H2 keeps a lock on the database, even when all connections are closed, and so when stopping Tomcat it hangs waiting on a thread, the process is still running.
The only way I managed to get H2 to not lock the database is by issueing the statement SHUTDOWN IMMEDIATELY command (the vanilla or compact did not release the lock).
This is performed in my ServletContextListener class in the contextDestroyed like this (I have omitted comments and log lines):
ServletContext ctx = servletContextEvent.getServletContext();
DataSource closeDS = databaseConnection.getDatasource();
Connection closeConn = null;
PreparedStatement closePS = null;
try {
closeConn = closeDS.getConnection();
closePS = closeConn.prepareStatement("SHUTDOWN IMMEDIATELY");
closePS.execute();
} catch (Exception ex) {
} finally {
if (closePS != null) {
try { closePS.close(); } catch (SQLException ex) {}
}
if (closeConn != null) {
try { closeConn.close(); } catch (SQLException ex) {}
}
}
try {
databaseConnection.close();
databaseConnection = null;
ctx.setAttribute("databaseConnection", null);
} catch(Exception e) {
}
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
} catch (Exception e) {
}
}
Now the lock is released Tomcat stops (although I still get the severe memory leak messages in the logs) but now I receive also a number of error stacks in the logs thus:
INFO: Illegal access: this web application instance has been stopped already.
Could not load java.lang.ThreadGroup.
The eventual following stack trace is caused by an error thrown
for debugging purposes as well as to attempt to terminate
the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1531)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1491)
at org.h2.engine.DatabaseCloser.reset(DatabaseCloser.java:43)
at org.h2.engine.Database.close(Database.java:1155)
at org.h2.engine.DatabaseCloser.run(DatabaseCloser.java:80)
10-sep-2013 13:31:41 org.apache.catalina.loader.WebappClassLoader loadClass
The question is: how can I shut down the database without causing illegal state exceptions. Is there something wrong in my code to call the shutdown command?
Why is this such an issue with H2? I do not have this issue with JBoss or Websphere where the application also runs using datasources provided by the container.
EDIT:
Found the solution. It was a problem with minifing the code while maven build process. Run the OrientDB in a Java Applet is possible.
I have problems starting the inmemory OrientDB in a Java Applet. I use a signed Applet with OrientDB version 1.0.1. Did someone implemented the OrientDB in a Applet and can verify that this is possible or could help me with this exception?
The exception I get:
2012-06-20 11:22:24:734 INFO OrientDB Server v1.0.1 is starting up... [OServer]Exception in thread "thread applet-de.test.all.Applet-1" sun.misc.ServiceConfigurationError: com.orientechnologies.orient.core.sql.OCommandExecutorSQLFactory: Provider com.orientechnologies.orient.core.sql.ODefaultCommandExecutorSQLFactory not found
at sun.misc.Service.fail(Service.java:129)
at sun.misc.Service.access$000(Service.java:111)
at sun.misc.Service$LazyIterator.next(Service.java:273)
at com.orientechnologies.orient.core.sql.OSQLEngine.getCommandFactories(OSQLEngine.java:186)
at com.orientechnologies.orient.core.sql.OSQLEngine.getCommandNames(OSQLEngine.java:216)
at com.orientechnologies.orient.core.sql.OSQLEngine.getCommand(OSQLEngine.java:239)
at com.orientechnologies.orient.core.sql.OCommandExecutorSQLDelegate.parse(OCommandExecutorSQLDelegate.java:41)
at com.orientechnologies.orient.core.sql.OCommandExecutorSQLDelegate.parse(OCommandExecutorSQLDelegate.java:31)
at com.orientechnologies.orient.core.storage.OStorageEmbedded.command(OStorageEmbedded.java:62)
at com.orientechnologies.orient.core.command.OCommandRequestTextAbstract.execute(OCommandRequestTextAbstract.java:60)
at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.createClass(OSchemaShared.java:218)
at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.createClass(OSchemaShared.java:164)
at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.createClass(OSchemaShared.java:145)
at com.orientechnologies.orient.core.metadata.schema.OSchemaShared.createClass(OSchemaShared.java:116)
at com.orientechnologies.orient.core.metadata.schema.OSchemaProxy.createClass(OSchemaProxy.java:65)
at com.orientechnologies.orient.core.metadata.security.OSecurityShared.createMetadata(OSecurityShared.java:259)
at com.orientechnologies.orient.core.metadata.security.OSecurityShared.create(OSecurityShared.java:202)
at com.orientechnologies.orient.core.metadata.security.OSecurityProxy.create(OSecurityProxy.java:37)
at com.orientechnologies.orient.core.metadata.OMetadata.create(OMetadata.java:68)
at com.orientechnologies.orient.core.db.record.ODatabaseRecordAbstract.create(ODatabaseRecordAbstract.java:171)
at com.orientechnologies.orient.core.db.ODatabaseWrapperAbstract.create(ODatabaseWrapperAbstract.java:53)
at com.orientechnologies.orient.core.db.ODatabaseRecordWrapperAbstract.create(ODatabaseRecordWrapperAbstract.java:54)
at com.orientechnologies.orient.server.OServer.loadStorages(OServer.java:451)
at com.orientechnologies.orient.server.OServer.loadConfiguration(OServer.java:394)
at com.orientechnologies.orient.server.OServer.startup(OServer.java:152)
at com.orientechnologies.orient.server.OServer.startup(OServer.java:143)
at com.orientechnologies.orient.server.OServer.startup(OServer.java:132)
at de.test.all.Applet$1.run(Applet.java:132)
at de.test.all.Applet$1.run(Applet.java:125)
at java.security.AccessController.doPrivileged(Native Method)
at de.test.all.Applet.init(Applet.java:124)
at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Plugin2Manager.java:1639)
at java.lang.Thread.run(Thread.java:680)
My Applet code to start the DB:
public class Applet extends java.applet.Applet {
OrientDbConfigurationLoader configLoader = null;
OServer server = null;
ODatabaseDocumentTx db = null;
#Override
public void init() {
AccessController.doPrivileged(new
PrivilegedAction<OServer>() {
public OServer run() {
configLoader = new OrientDbConfigurationLoader("db/", "test");
try {
server = OServerMain.create();
server.startup(configLoader.loadDefaultConfig());
server.activate();
} catch (InstanceAlreadyExistsException e) {
server = OServerMain.server();
} catch (Exception e) {
System.out.println("Something went wrong while the server should start");
e.printStackTrace();
}
try {
db = new ODatabaseDocumentTx("memory:temp");
db = db.open(OrientDbConfigurationLoader.USERNAME, OrientDbConfigurationLoader.PASSWORD);
} catch (Exception e) {
System.out.println("Can't init the in-memory db.");
e.printStackTrace();
}
return null;
}
});
}
}
the problem seems the usage of Java Service Registry. Look at:
OClassLoaderHelper.lookupProviderWithOrientClassLoader()
it calls:
ServiceRegistry.lookupProviders(clazz);
I've just added in SVN trunk (r5909) this check:
try {
factories.add(ite.next());
} catch (Exception e) {
OLogManager.instance().warn(null, "Cannot load OCommandExecutorSQLFactory instance from service registry", e);
}
In this way a WARN is dumped but you can continue to configure your own factories if needed.