Package org.apache.tuscany.sca.implementation.bpel.ode

Source Code of org.apache.tuscany.sca.implementation.bpel.ode.EmbeddedODEServer

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.apache.tuscany.sca.implementation.bpel.ode;

import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.transaction.TransactionManager;
import javax.xml.namespace.QName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.bpel.dao.BpelDAOConnectionFactoryJDBC;
import org.apache.ode.bpel.engine.BpelServerImpl;
import org.apache.ode.bpel.engine.CountLRUDehydrationPolicy;
import org.apache.ode.bpel.evt.BpelEvent;
import org.apache.ode.bpel.evt.CorrelationMatchEvent;
import org.apache.ode.bpel.evt.NewProcessInstanceEvent;
import org.apache.ode.bpel.evt.ProcessMessageExchangeEvent;
import org.apache.ode.bpel.iapi.BpelEventListener;
import org.apache.ode.bpel.iapi.Scheduler;
import org.apache.ode.bpel.memdao.BpelDAOConnectionFactoryImpl;
import org.apache.ode.il.config.OdeConfigProperties;
import org.apache.ode.il.dbutil.Database;
import org.apache.ode.scheduler.simple.JdbcDelegate;
import org.apache.ode.scheduler.simple.SimpleScheduler;
import org.apache.ode.utils.GUID;
import org.apache.tuscany.sca.assembly.EndpointReference;
import org.apache.tuscany.sca.implementation.bpel.BPELImplementation;
import org.apache.tuscany.sca.runtime.RuntimeComponent;
import org.eclipse.core.runtime.FileLocator;



/**
* Embedded ODE process server
*
* @version $Rev: 922611 $ $Date: 2010-03-13 17:03:50 +0000 (Sat, 13 Mar 2010) $
*/
public class EmbeddedODEServer {
    private static final String TUSCANY_IMPL_BPEL_DBLOCATION = "TUSCANY_IMPL_BPEL_DBLOCATION";
   
    protected final Log __log = LogFactory.getLog(getClass());

    private boolean _initialized;

    private OdeConfigProperties _config;

    private TransactionManager _txMgr;

    private Database _db;

    private File _workRoot;

    private BpelDAOConnectionFactoryJDBC _daoCF;

    private BpelServerImpl _bpelServer;

    private Scheduler _scheduler;
   
    protected ExecutorService _executorService;

    private Map<QName, RuntimeComponent> tuscanyRuntimeComponents = new ConcurrentHashMap<QName, RuntimeComponent>();
   
    private Map<String, Long> mexToProcessMap = new ConcurrentHashMap<String, Long>();
   
    private Map<Long, Map<String, EndpointReference>> callbackMap = new ConcurrentHashMap<Long, Map<String, EndpointReference>>();
   
    private final Lock metadataLock     = new ReentrantLock();
    private final Condition mexAdded      = metadataLock.newCondition();
    private final Condition callbackAdded    = metadataLock.newCondition();
      
    public EmbeddedODEServer(TransactionManager txMgr) {
        _txMgr = txMgr;
    }
   
    public void init() throws ODEInitializationException {

        Properties p = System.getProperties();
        p.put("derby.system.home", "target");

        Properties confProps = new Properties();
        confProps.put("openjpa.jdbc.SynchronizeMappings", "buildSchema(ForeignKeys=false)");
       
        _config = new OdeConfigProperties(confProps, "ode-sca");

        // Setting work root as the directory containing our database
        try {
          _workRoot = getDatabaseLocationAsFile();
        } catch (URISyntaxException e) {
            throw new ODEInitializationException(e);
        }

        initTxMgr();
        initPersistence();
        initBpelServer();

        try {
            _bpelServer.start();
        } catch (Exception ex) {
            String errmsg = "An error occured during the ODE BPEL server startup.";
            __log.error(errmsg, ex);
            throw new ODEInitializationException(errmsg, ex);
        }
       
        // Start ODE scheduler
        _scheduler.start();
       
        __log.info("ODE BPEL server started.");
        _initialized = true;

    } // end method init()
   
    /**
     * Gets the location of the database used for the ODE BPEL engine as a File object for
     * the directory containing the database
     * @return
     * @throws ODEInitializationException
     * @throws URISyntaxException
     */
    private File getDatabaseLocationAsFile() throws ODEInitializationException, URISyntaxException {
        File locationFile   = null;
        URL dbLocation    = null;

        // An environment variable to set the path to the DB
        String dbFile = System.getenv(TUSCANY_IMPL_BPEL_DBLOCATION);
        if( dbFile != null ) {
            try {
                locationFile = new File(dbFile).getParentFile();
            } catch (Exception e ) {
                System.out.println("Environment variable " + TUSCANY_IMPL_BPEL_DBLOCATION + " has the wrong format: " + dbFile);
                System.out.println("Exception is: " + e.getClass().toString() + " " + e.getMessage());
            } // end try
        } else {
            dbLocation = getClass().getClassLoader().getResource("jpadb");
            if (dbLocation == null) {
                throw new ODEInitializationException("Couldn't find database in the classpath:" +
                " try setting the " + TUSCANY_IMPL_BPEL_DBLOCATION + " environment variable");
            }
            // Handle OSGI bundle case
            if( dbLocation.getProtocol() == "bundleresource" ) {
                try {
                    dbLocation = FileLocator.toFileURL( dbLocation );
                } catch (Exception ce ) {
                    throw new ODEInitializationException("Couldn't find database in the OSGi bundle");
                } // end try
            } // end if
            locationFile = new File(dbLocation.toURI()).getParentFile();
        } // end if

        return locationFile;
    } // end method getDatabaseLocationAsFile

    private void initTxMgr() {
        if(_txMgr == null) {
            try {
                GeronimoTxFactory txFactory = new GeronimoTxFactory();
                _txMgr = txFactory.getTransactionManager();
            } catch (Exception e) {
                __log.fatal("Couldn't initialize a transaction manager using Geronimo's transaction factory.", e);
                throw new ODEInitializationException("Couldn't initialize a transaction manager using " + "Geronimo's transaction factory.", e);
            }           
        }
    }

    private void initPersistence() {
        _db = new Database(_config);
        _db.setTransactionManager(_txMgr);
        _db.setWorkRoot(_workRoot);

        try {
            _db.start();
            _daoCF = _db.createDaoCF();
        } catch (Exception ex) {
            String errmsg = "Error while configuring ODE persistence.";
            __log.error(errmsg, ex);
            throw new ODEInitializationException(errmsg, ex);
        }
    }
 
    private void initBpelServer() {
        if (__log.isDebugEnabled()) {
            __log.debug("ODE initializing");
        }
        ThreadFactory threadFactory = new ThreadFactory() {
            int threadNumber = 0;
            public Thread newThread(Runnable r) {
                threadNumber += 1;
                Thread t = new Thread(r, "ODEServer-"+threadNumber);
                t.setDaemon(true);
                return t;
            }
        };

        _executorService = Executors.newCachedThreadPool(threadFactory);
       
        // executor service for long running bulk transactions
        ExecutorService _polledRunnableExecutorService = Executors.newCachedThreadPool(new ThreadFactory() {
            int threadNumber = 0;
            public Thread newThread(Runnable r) {
                threadNumber += 1;
                Thread t = new Thread(r, "PolledRunnable-"+threadNumber);
                t.setDaemon(true);
                return t;
            }
        });

        _bpelServer = new BpelServerImpl();
        _scheduler = createScheduler();
        _scheduler.setJobProcessor(_bpelServer);
       
        BpelServerImpl.PolledRunnableProcessor polledRunnableProcessor = new BpelServerImpl.PolledRunnableProcessor();
        polledRunnableProcessor.setPolledRunnableExecutorService(_polledRunnableExecutorService);
        polledRunnableProcessor.setContexts(_bpelServer.getContexts());
        //_scheduler.setPolledRunnableProcesser(polledRunnableProcessor);

        _bpelServer.setDaoConnectionFactory(_daoCF);
        _bpelServer.setInMemDaoConnectionFactory(new BpelDAOConnectionFactoryImpl(_scheduler));
       
        _bpelServer.setEndpointReferenceContext( new ODEEprContext() );
        _bpelServer.setMessageExchangeContext(new ODEMessageExchangeContext(this));
        _bpelServer.setBindingContext(new ODEBindingContext());
        _bpelServer.setScheduler(_scheduler);
        if (_config.isDehydrationEnabled()) {
            CountLRUDehydrationPolicy dehy = new CountLRUDehydrationPolicy();
            dehy.setProcessMaxAge(_config.getDehydrationMaximumAge());
            dehy.setProcessMaxCount(_config.getDehydrationMaximumCount());
            _bpelServer.setDehydrationPolicy(dehy);
        }
             
        _bpelServer.setConfigProperties(_config.getProperties());
        _bpelServer.init();
        _bpelServer.setInstanceThrottledMaximumCount(_config.getInstanceThrottledMaximumCount());
        _bpelServer.setProcessThrottledMaximumCount(_config.getProcessThrottledMaximumCount());
        _bpelServer.setProcessThrottledMaximumSize(_config.getProcessThrottledMaximumSize());
        _bpelServer.setHydrationLazy(_config.isHydrationLazy());
        _bpelServer.setHydrationLazyMinimumSize(_config.getHydrationLazyMinimumSize());
   
        // Register event listener on the BPEL server
        _bpelServer.registerBpelEventListener( new ODEEventListener( this, _bpelServer) );
    } // end method initBpelLServer

    public void stop() throws ODEShutdownException {
        if(_bpelServer != null) {
            try {
                __log.debug("Stopping BPEL Embedded server");
                _bpelServer.shutdown();
                _bpelServer = null;
            } catch (Exception ex) {
                __log.debug("Error stopping BPEL server");
            }
        }

        if(_scheduler != null) {
            try {
                __log.debug("Stopping scheduler");
                _scheduler.shutdown();
                _scheduler = null;
            } catch (Exception ex) {
                __log.debug("Error stopping scheduler");
            }
        }
       
        if(_daoCF != null) {
            try {
                __log.debug("Stopping DAO");
                _daoCF.shutdown();
                _daoCF = null;
            } catch (Exception ex) {
                __log.debug("Error stopping DAO");
            }
        }
       
        if(_db != null) {
            try {
                __log.debug("Stopping DB");
                _db.shutdown();
                _db = null;
            } catch (Exception ex) {
                __log.debug("Error stopping DB");
            }
        }
       
        if(_txMgr != null) {
            try {
                __log.debug("Stopping Transaction Manager");
                _txMgr = null;
            } catch (Exception ex) {
                __log.debug("Error stopping Transaction Manager");
            }
        }
    }

    protected Scheduler createScheduler() {
      Properties odeProperties = new Properties();
      // TODO Find correct values for these properties - MJE 22/06/2009
      odeProperties.put("ode.scheduler.queueLength", "100" );
      odeProperties.put("ode.scheduler.immediateInterval", "30000" );
      odeProperties.put("ode.scheduler.nearFutureInterval", "600000" );
      odeProperties.put("ode.scheduler.staleInterval", "100000" );
     
        SimpleScheduler scheduler = new SimpleScheduler(new GUID().toString(),
                                            new JdbcDelegate(_db.getDataSource()),
                                                        odeProperties );
        scheduler.setExecutorService(_executorService);
        scheduler.setTransactionManager(_txMgr);

        return scheduler;
    }

    public boolean isInitialized() {
        return _initialized;
    }

    public BpelServerImpl getBpelServer() {
        return _bpelServer;
    }
   
    public Scheduler getScheduler() {
        return _scheduler;
    }
   
    public ExecutorService getExecutor() {
      return _executorService;
    }

    /**
     * Deploy the BPEL process implementation to the ODE Engine
     * @param d - ODEDeployment structure
     * @param implementation - the BPEL Implementation
     * @param component - the SCA component which uses the implementation
     */
    public void deploy(ODEDeployment d, BPELImplementation implementation, RuntimeComponent component ) {
        try {
          TuscanyProcessConfImpl processConf = new TuscanyProcessConfImpl( implementation, component );
          _bpelServer.register(processConf);
          d.setProcessConf(processConf);
          __log.debug("Completed calling new Process deployment code...");
        } catch (Exception ex) {
            String errMsg = ">>> DEPLOY: Unexpected exception during deploy of BPEL. /n Component = "
                           + component.getName()
                           + " implementation = "
                           + implementation.getProcess()
                           + ex.getMessage();
            __log.debug(errMsg, ex);
            throw new ODEDeploymentException(errMsg,ex);
        }
    }

    /**
     * Undeploy the BPEL process implementation from the ODE Engine
     * @param d - ODEDeployment structure
     */
    public void undeploy(ODEDeployment d) {
      TuscanyProcessConfImpl processConf = d.getProcessConf();
      if( processConf != null ) {
        processConf.stop();
      } // end if
    } // end method undeploy
   
    public void registerTuscanyRuntimeComponent(QName processName,RuntimeComponent componentContext) {
        tuscanyRuntimeComponents.put(processName, componentContext);
    }
       
    public RuntimeComponent getTuscanyRuntimeComponent(QName processName) {
        return tuscanyRuntimeComponents.get(processName);
    }
   
    /**
     * Records a connection between a MessageExchange ID and a Process Instance ID
     * @param mexID
     * @param processID
     */
    public void addMexToProcessIDLink( String mexID, Long processID ) {
      //System.out.println("Add mapping Mex - ProcessID = " + mexID + " " + processID.toString());
      if( mexID == null ) {
        //System.out.println("Mex ID is null !");
        return;
      } // end if
      metadataLock.lock();
      try {
        mexToProcessMap.put(mexID, processID);
        mexAdded.signalAll();
        return;
      } catch (Exception e) {
        return;
      } finally {
        metadataLock.unlock();
      } // end try
    } // end method addMexToProcessIDLink( mexID, processID )
   
    /**
     * Connects from a MessageExchangeID to a Process Instance ID
     * @param mexID - the MessageExchange ID
     * @return - a Long which is the Process Instance ID
     */
    public Long getProcessIDFromMex( String mexID ) {
      //System.out.println("Get mapping for Mex: " + mexID);
      metadataLock.lock();
      try {
        Long processID = mexToProcessMap.get(mexID);
        while( processID == null ) {
          mexAdded.await();
          processID = mexToProcessMap.get(mexID);
        } // end while
        return processID;
      } catch (Exception e) {
        return null;
      } finally {
        metadataLock.unlock();
      } // end try

    } // end method getProcessIDFromMex
   
    /**
     * Remove the connection between a Message Exchange ID and a Process Instance ID
     * @param mexID - the Message Exchange ID
     */
    public void removeMexToProcessIDLink( String mexID ) {
      mexToProcessMap.remove(mexID);
    } // end method removeMexToProcessIDLink
   
    /**
     * Stores the metadata for a Callback
     * @param processID - Process ID of the BPEL Process Instance for which this callback applies
     * @param serviceName - the name of the service which has the callback
     * @param callbackEndpoint - a Tuscany Endpoint which is the target of the callback
     */
    public void saveCallbackMetadata( Long processID, String serviceName, EndpointReference callbackEPR ) {
      //System.out.println("Save callback metadata: ProcessID " + processID.toString() + " service: " + serviceName);
      metadataLock.lock();
      try {
        Map<String, EndpointReference> processMap = callbackMap.get(processID);
        if( processMap == null ) {
          processMap = new ConcurrentHashMap<String, EndpointReference>();
          callbackMap.put(processID, processMap);
        } // end if
        // Put the mapping of service name to callback endpoint - note that this overwrites any
        // previous mapping for the same service name
        processMap.put(serviceName, callbackEPR);
        callbackAdded.signalAll();
      } finally {
        metadataLock.unlock();
      } // end try
    } // end saveCallbackMetadata
   
    /**
     * Get the metadata for a Callback, based on a BPEL Process Instance ID and a Service name
     * @param processID - the BPEL Process Instance ID
     * @param serviceName - the service name
     * @return - and Endpoint which is the Callback endpoint for the service for this process instance.
     * Returns null if there is no callback metadata for this service.
     */
    public EndpointReference getCallbackMetadata( Long processID, String serviceName ) {
      EndpointReference theEPR;
      //System.out.println("Get callback metadata: ProcessID " + processID.toString() + " service: " + serviceName);
     
      metadataLock.lock();
      try {
        while(true) {
          Map<String, EndpointReference> processMap = callbackMap.get(processID);
          theEPR = processMap.get(serviceName);
          if( theEPR != null ) return theEPR;
          callbackAdded.await();
        } // end while
      } catch (Exception e) {
        return null;
      } finally {
        metadataLock.unlock();
      } // end try
    } // end method getCallbackMetadata
   
    /**
     * Removes the metadata for a Callback
     * @param processID - the Process Instance ID of the process instance to which the callback metadata applies
     * @param serviceName - the service name for the service which has a callback - can be NULL, in which case ALL
     * callback metadata for the process instance is removed
     */
    public void removeCallbackMetadata( Long processID, String serviceName ) {
     
      if( serviceName == null ) {
        callbackMap.remove(processID);
      } else {
        Map<String, EndpointReference> processMap = callbackMap.get(processID);
          processMap.remove(serviceName);
      } // end if
     
    } // end method removeCallbackMetadata
   
    private class ODEEventListener implements BpelEventListener {
     
      private EmbeddedODEServer ODEServer;
      private BpelServerImpl bpelServer;
     
      ODEEventListener( EmbeddedODEServer ODEServer, BpelServerImpl bpelServer ) {
        this.ODEServer       = ODEServer;
        this.bpelServer     = bpelServer;
      } // end constructor

      /**
       * Method which receives events from the ODE Engine as processing proceeds
       */
    public void onEvent(BpelEvent bpelEvent) {
      if( bpelEvent instanceof ProcessMessageExchangeEvent ||
          bpelEvent instanceof NewProcessInstanceEvent ||
          bpelEvent instanceof CorrelationMatchEvent ) {
        handleProcMexEvent( (ProcessMessageExchangeEvent) bpelEvent );
        return;
      } // end if
     
    } // end method onEvent
   
    /**
     * Handle a ProcessMessageExchangeEvent
     * - the important aspect of this event is that it establishes a connection between a MessageExchange object
     * and the BPEL Process instance to which it relates.
     * @param bpelEvent - the ProcessMessageExchangeEvent
     */
    private void handleProcMexEvent( ProcessMessageExchangeEvent bpelEvent) {
      // Extract the message ID and the process instance ID - it is the connection between these
      // that is vital to know
      String mexID   = bpelEvent.getMessageExchangeId();
      Long processID   = bpelEvent.getProcessInstanceId();
      ODEServer.addMexToProcessIDLink( mexID, processID );
    } // end method handleProcMexEvent

    public void shutdown() {
      // Intentionally left blank   
    }

    public void startup(Properties configProperties) {
      // Intentionally left blank   
    }
     
    } // end Class BPELEventListener
}
TOP

Related Classes of org.apache.tuscany.sca.implementation.bpel.ode.EmbeddedODEServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.