All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.openbp.server.ProcessServer Maven / Gradle / Ivy
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openbp.server;
import java.util.Iterator;
import java.util.List;
import javax.annotation.PostConstruct;
import org.openbp.common.ExceptionUtil;
import org.openbp.common.application.Application;
import org.openbp.common.generic.msgcontainer.MsgItem;
import org.openbp.common.generic.msgcontainer.StandardMsgContainer;
import org.openbp.common.logger.LogUtil;
import org.openbp.core.CoreModule;
import org.openbp.core.OpenBPException;
import org.openbp.core.engine.EngineException;
import org.openbp.core.model.Model;
import org.openbp.core.remote.ClientConnectionInfo;
import org.openbp.server.context.TokenContextService;
import org.openbp.server.engine.Engine;
import org.openbp.server.engine.EngineRunner;
import org.openbp.server.engine.debugger.Debugger;
import org.openbp.server.engine.debugger.DebuggerImpl;
import org.openbp.server.remote.RemoteConnectorServer;
import org.openbp.server.scheduler.ProcessScheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
/**
* This class is the main anchor point of an OpenBP server.
* It performs all server startup and shutdown tasks.
* Note that you must call the {@link #initialize} method before you can request any services from the server.
*
* @author Heiko Erhardt
*/
@Service("processServer")
public class ProcessServer extends CoreModule
implements ApplicationContextAware
{
// Components configured by Spring
/** Classpath name of the server's properties resource or null */
private String propertiesResourceName = "OpenBP-Server.properties";
@Autowired
private ProcessFacade processFacade;
@Autowired
private Engine engine;
@Autowired
private EngineRunner engineRunner;
@Autowired
private TokenContextService tokenContextService;
@Autowired
private Debugger debugger;
@Autowired(required=false)
private ProcessScheduler processScheduler;
@Autowired @Qualifier("exportedService")
private List services;
private ClientConnectionInfo connectionInfo;
private boolean initialized;
private boolean initializing;
private ServerShutdownHook serverShutdownHook;
private RemoteConnectorServer remoteConnectorServer;
/** Spring application context if the process server was instantiated by the Spring framework */
private ApplicationContext applicationContext;
/**
* Constructor to be used by the Spring framework only, class needs to be autowired.
* You might also use the {@link ProcessServerFactory} for construction.
*/
public ProcessServer()
{
}
//////////////////////////////////////////////////
// @@ Initialization
//////////////////////////////////////////////////
/**
* Implementation of the ApplicationContextAware interface.
* See org.springframework.context.ApplicationContextAware.
* Called by the Spring framework after bean construction.
*
* @param applicationContext Spring application context the process server was instantiated by the Spring framework
*/
public void setApplicationContext(ApplicationContext applicationContext)
{
this.applicationContext = applicationContext;
}
/**
* Gets the spring application context if the process server was instantiated by the Spring framework.
*/
public ApplicationContext getApplicationContext()
{
return applicationContext;
}
/**
* Sets the classpath name of the server's properties resource.
* @param propertiesResourceName Resource name or null (default: "OpenBP-Server.properties")
*/
public void setPropertiesResourceName(String propertiesResourceName)
{
this.propertiesResourceName = propertiesResourceName;
}
/**
* Initializes the server.
* Call this method before requesting any services from the core.
* This method will also be called from the IoC container that supports the JSR 250 @PostConstruct annotation.
*
* @throws OpenBPException On severe error
*/
@PostConstruct
public synchronized void initialize()
{
if (initialized || initializing)
return;
try
{
// Prevent endless recursion
initializing = true;
determineRootDir();
if (propertiesResourceName != null)
{
Application.registerPropertyResource(propertiesResourceName, 80, false);
}
// Note: It is important to keep the order of these statements!
// Perform the core initialization
super.initialize();
// Reads all models
initModels();
// Register a shutdown hook that allows correct database shutdown
registerShutdownHook();
// Initialize the remote services
initRemoting();
// TODO FIX 5 The DebuggerImpl.initialize method should be called using @PostConstruct - Need to convert SettingUtil to service to do this
if (debugger instanceof DebuggerImpl)
{
((DebuggerImpl) debugger).initialize();
}
initialized = true;
}
finally
{
initializing = false;
}
}
/**
* Initializes the model manager.
*
* @throws OpenBPException On error
*/
private void initModels()
{
LogUtil.info(getClass(), "Loading models...");
// Read all models
getModelMgr().readModels();
// Initialize the models
getModelMgr().initializeModels();
// Print any errors to stderr
StandardMsgContainer msgContainer = getModelMgr().getMsgContainer();
for (Iterator it = msgContainer.getMsgs(); it.hasNext();)
{
MsgItem msgItem = (MsgItem) it.next();
LogUtil.error(getClass(), msgItem.getFormattedMsgWithSource());
}
msgContainer.clearMsgs();
LogUtil.info(getClass(), "Model load complete.");
}
/**
* Registers the services and start up the RMI registry.
*
* @throws OpenBPException On error
*/
private void initRemoting()
{
if (services == null)
{
// No services to publish
return;
}
try
{
// Determine remote connection properties
if (connectionInfo == null)
{
// Load connection info from properties file if not specified in the Spring config file
connectionInfo = new ClientConnectionInfo();
connectionInfo.loadFromProperties();
}
// Make the remote connector known to the RMI registry
if (connectionInfo.isEnabled())
{
remoteConnectorServer = new RemoteConnectorServer();
for (Iterator it = services.iterator(); it.hasNext();)
{
remoteConnectorServer.registerService(it.next());
}
remoteConnectorServer.setConnectionInfo(connectionInfo);
remoteConnectorServer.bindToRegistry();
}
}
catch (Exception e)
{
throw new EngineException("Initialization", "Error initializing services.", e);
}
}
//////////////////////////////////////////////////
// @@ Shutdown
//////////////////////////////////////////////////
/**
* Performs shutdown of the process server using a 60 second timeout.
*
* @param unregisterHook
* true Unregister the VM's shutdown hook. Note that this may not be done during VM shutdown! (when invoked due to servlet reaload etc.)
* false Do not unregister the hook (when invoked due to VM termination)
* Calls shutdownModel for each loaded model.
*/
public boolean shutdown(boolean unregisterHook)
{
return shutdown(60000L, unregisterHook);
}
/**
* Performs shutdown of the process server.
* Before the server shutdown, the engine runner (if present) will be shut down (see {@link EngineRunner#waitForStop}).
* Also calls {@link Model#shutdownModel} for each loaded model.
* The method will ignore any exception, however, they will be logged.
*
* @param timeoutMS Timeout in milliseconds for the engine runner shutdown.
* If this value is 0, the method will just check if everything has completed, but will not wait for any processes.
* If this value is -1, no timeout will apply (i. e. the method will definately wait
* until all context executions have finished).
* @param unregisterHook
* true Unregister the VM's shutdown hook. Note that this may not be done during VM shutdown!
* (when invoked due to servlet reaload etc.)
* false Do not unregister the hook (when invoked due to VM termination)
* @return true if no context is currently executing and there were no exceptions during shutdown,
* false if either the engine runner shutdown timeout has elapsed or there have been exceptions during the shutdown.
*/
public boolean shutdown(long timeoutMS, boolean unregisterHook)
{
boolean ret = true;
synchronized (this)
{
if (initialized)
{
LogUtil.info(getClass(), "Shutting down the OpenBP engine...");
try
{
if (getEngineRunner() != null)
{
ret = getEngineRunner().waitForStop(timeoutMS);
}
if (remoteConnectorServer != null)
{
try
{
remoteConnectorServer.unbindFromRegistry();
}
catch (Exception e)
{
// Ignore errors when unbing, we are shutting down anyway
// We also don't log this one.
ret = false;
}
remoteConnectorServer = null;
}
// Shutdown all models
for (Iterator it = getModelMgr().getModels().iterator(); it.hasNext();)
{
Model model = (Model) it.next();
try
{
shutdownModel(model);
}
catch (Exception e)
{
LogUtil.error(getClass(), "Error during shutdown of model.", model.getQualifier(), e);
ret = false;
}
}
super.shutdown(unregisterHook);
// TODONOW Shutdown triggered by container instead
if (unregisterHook)
{
unregisterShutdownHook();
}
}
catch (Exception e)
{
LogUtil.error(getClass(), "Error during OpenBP engine shutdown.", e);
ret = false;
}
finally
{
LogUtil.info(getClass(), "OpenBP engine shutdown complete.");
initialized = false;
}
}
}
return ret;
}
/**
* Shuts down the given model and its sub models.
*
* @param model Model to shut down or null for all models
*/
private void shutdownModel(Model model)
{
// Shut down the model; catch any exception
// TODO Feature 5 Trigger the appropriate model event
try
{
model.shutdownModel();
}
catch (Exception e)
{
LogUtil.error(getClass(), "Error while shutting down model $0", model.getQualifier(), e);
}
}
/**
* Registers a shutdown hook that allows correct database shutdown.
*/
private void registerShutdownHook()
{
// TODO FIX 3 Maybe we should register with the app context shutdown hook instead the JDK runtime...
serverShutdownHook = new ServerShutdownHook();
Runtime.getRuntime().addShutdownHook(serverShutdownHook);
}
/**
* Registers a shutdown hook that allows correct database shutdown.
*/
private void unregisterShutdownHook()
{
if (serverShutdownHook != null)
{
Runtime.getRuntime().removeShutdownHook(serverShutdownHook);
serverShutdownHook = null;
}
}
/**
* Server shutdown hook.
*/
private class ServerShutdownHook extends Thread
{
/**
* Constructor.
*/
public ServerShutdownHook()
{
// This thread must not prevent VM shutdown.
setDaemon(true);
}
/**
* Called when the virtual machine is about to terminate.
* This can be because the exit method has been called or CTRL+C has been pressed.
*/
public void run()
{
ProcessServer.this.shutdown(false);
}
}
//////////////////////////////////////////////////
// @@ Components setters/getters
//////////////////////////////////////////////////
/**
* Gets the process facade.
*/
public ProcessFacade getProcessFacade()
{
initialize();
return processFacade;
}
/**
* Sets the process facade.
*/
public void setProcessFacade(ProcessFacade processFacade)
{
this.processFacade = processFacade;
}
/**
* Gets the engine.
*/
public Engine getEngine()
{
initialize();
return engine;
}
/**
* Sets the engine.
*/
public void setEngine(Engine engine)
{
this.engine = engine;
}
/**
* Gets the engine runner.
*/
public EngineRunner getEngineRunner()
{
initialize();
return engineRunner;
}
/**
* Sets the engine runner.
*/
public void setEngineRunner(EngineRunner engineRunner)
{
this.engineRunner = engineRunner;
}
/**
* Gets the token context service.
*/
public TokenContextService getTokenContextService()
{
initialize();
return tokenContextService;
}
/**
* Sets the token context service.
*/
public void setTokenContextService(TokenContextService tokenContextService)
{
this.tokenContextService = tokenContextService;
}
/**
* Gets the process scheduler.
*/
public ProcessScheduler getProcessScheduler()
{
initialize();
return processScheduler;
}
/**
* Sets the process scheduler.
*/
public void setProcessScheduler(ProcessScheduler processScheduler)
{
this.processScheduler = processScheduler;
}
/**
* Sets the list of service implementations.
*/
public void setServices(List services)
{
this.services = services;
}
/**
* Sets the connection info.
*/
public void setConnectionInfo(ClientConnectionInfo connectionInfo)
{
this.connectionInfo = connectionInfo;
}
//////////////////////////////////////////////////
// @@ Main class for simple test server mode
//////////////////////////////////////////////////
/**
* Main method for simple server test mode.
*
* @param arguments Command line argument array
*/
public static void main(String[] arguments)
{
long time = System.currentTimeMillis();
try
{
// Initialize the server
Application.setArguments(arguments);
// Start up the server
ProcessServer processServer = new ProcessServerFactory().createProcessServer();
// Compute startup time and print startup message
time = System.currentTimeMillis() - time;
String startedUpMessage = "OpenBP test server startup complete [" + time + " ms].";
LogUtil.info(ProcessServer.class, startedUpMessage);
processServer.shutdown(true);
}
catch (Exception e)
{
ExceptionUtil.printTrace("Error initializing OpenBP server", e);
System.exit(1);
}
}
}