org.camunda.bpm.application.impl.JakartaServletProcessApplication Maven / Gradle / Ivy
/*
* 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 jakarta.servlet.ServletContext;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import java.lang.ref.WeakReference;
import org.camunda.bpm.application.AbstractProcessApplication;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import org.camunda.bpm.engine.impl.util.JakartaClassLoaderUtil;
/**
*
* 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 5.0 container it is sufficient adding a custom
* subclass of {@link JakartaServletProcessApplication} 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.
*
*
* 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 JakartaServletProcessApplication} and does not cache any classes loaded using
* the Process Application classloader.
*
*
*/
public class JakartaServletProcessApplication extends AbstractServletProcessApplication implements ServletContextListener {
protected ServletContext servletContext;
@Override
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 (getClass().equals(JakartaServletProcessApplication.class)) {
return JakartaClassLoaderUtil.getServletContextClassloader(sce);
} else {
return JakartaClassLoaderUtil.getClassloader(getClass());
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// perform lifecycle stop
undeploy();
// clear the reference
if (reference != null) {
reference.clear();
}
reference = null;
}
public ServletContext getServletContext() {
return servletContext;
}
}