All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.camunda.bpm.application.impl.ServletProcessApplication Maven / Gradle / Ivy

There is a newer version: 7.23.0-alpha2
Show newest version
/*
 * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. Camunda licenses this file to you under the Apache License,
 * Version 2.0; 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.camunda.bpm.application.impl;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.camunda.bpm.application.AbstractProcessApplication;
import org.camunda.bpm.application.ProcessApplicationInfo;
import org.camunda.bpm.application.ProcessApplicationReference;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import org.camunda.bpm.engine.impl.util.ClassLoaderUtil;

/**
 * 

A {@link AbstractProcessApplication} Implementation to be used in a Servlet container environment.

* *

This class implements the {@link ServletContextListener} interface and can thus participate in the * deployment lifecycle of your web application.

* *

Usage

*

In a Servlet 3.0 container it is sufficient adding a custom subclass of * {@link ServletProcessApplication} annotated with {@literal @}ProcessApplication to your * application: *

 * {@literal @}ProcessApplication("Loan Approval App")
 * public class LoanApprovalApplication extends ServletProcessApplication {
 * // empty implementation
 * }
 * 
* This, in combination with a META-INF/processes.xml file is sufficient for making sure * that the process application class is picked up at runtime.

*

In a Servlet 2.5 container, the process application can be added as a web listener * to your project's web.xml

*
 * {@literal <}?xml version="1.0" encoding="UTF-8"?{@literal >}
 * {@literal <}web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
 *       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 *       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"{@literal >}
 *
 * {@literal <}listener{@literal >}
 *   {@literal <}listener-class{@literal >}org.my.project.MyProcessApplication{@literal <}/listener-class{@literal >}
 * {@literal <}/listener{@literal >}
 *{@literal <}/web-app{@literal >}
 * 
*

* *

Invocation Semantics

*

When the {@link #execute(java.util.concurrent.Callable)} method is invoked, the servlet process * application modifies the context classloader of the current Thread to the classloader that loaded * the application-provided subclass of this class. This allows *

    *
  • the process engine to resolve {@link JavaDelegate} implementations using the classloader * of the process application
  • *
  • In apache tomcat this allows you to resolve Naming Resources (JNDI) form the naming * context of the process application. JNDI name resolution is based on the TCCL in Apache Tomcat.
  • *
*

* * *
 *                        Set TCCL of Process Application
 *                                     |
 *                                     |  +--------------------+
 *                                     |  |Process Application |
 *                       invoke        v  |                    |
 *      ProcessEngine -----------------O--|--> Java Delegate   |
 *                                        |                    |
 *                                        |                    |
 *                                        +--------------------+
 *
 * 
* *

Process Application Reference

*

The process engine holds a {@link WeakReference} to the {@link ServletProcessApplication} and does not cache any * classes loaded using the Process Application classloader.

* * * @author Daniel Meyer * @author Thorben Lindhauer * */ public class ServletProcessApplication extends AbstractProcessApplication implements ServletContextListener { protected String servletContextName; protected String servletContextPath; protected ProcessApplicationReferenceImpl reference; protected ClassLoader processApplicationClassloader; protected ServletContext servletContext; protected String autodetectProcessApplicationName() { String name = (servletContextName != null && !servletContextName.isEmpty()) ? servletContextName : servletContextPath; if(name.startsWith("/")) { name = name.substring(1); } return name; } public ProcessApplicationReference getReference() { if(reference == null) { reference = new ProcessApplicationReferenceImpl(this); } return reference; } public void contextInitialized(ServletContextEvent sce) { servletContext = sce.getServletContext(); servletContextPath = servletContext.getContextPath(); servletContextName = sce.getServletContext().getServletContextName(); processApplicationClassloader = initProcessApplicationClassloader(sce); // perform lifecycle start deploy(); } protected ClassLoader initProcessApplicationClassloader(ServletContextEvent sce) { if (isServlet30ApiPresent(sce) && getClass().equals(ServletProcessApplication.class)) { return ClassLoaderUtil.getServletContextClassloader(sce); } else { return ClassLoaderUtil.getClassloader(getClass()); } } private boolean isServlet30ApiPresent(ServletContextEvent sce) { return sce.getServletContext().getMajorVersion() >= 3; } public ClassLoader getProcessApplicationClassloader() { return processApplicationClassloader; } public void contextDestroyed(ServletContextEvent sce) { // perform lifecycle stop undeploy(); // clear the reference if(reference != null) { reference.clear(); } reference = null; } public Map getProperties() { Map properties = new HashMap(); // set the servlet context path as property properties.put(ProcessApplicationInfo.PROP_SERVLET_CONTEXT_PATH, servletContextPath); return properties; } public ServletContext getServletContext() { return servletContext; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy