Embedding Cockpit and Tasklist into Spring embedded Tomcat

1,867 views
Skip to first unread message

TobiasH

unread,
Apr 9, 2014, 9:45:40 AM4/9/14
to camunda-...@googlegroups.com
Hi,

we use the embedded Tomcat out of the box from the Spring Framework (spring-boot-starter-web).

I have successfully created a Spring Application which starts a processengine on the embedded Tomcat.

But now i have problems to embed the Cockpit into this embedded Tomcat. I only found tutorials which show me how to deploy the Camunda-webapp on a normal Vanilla Tomcat (https://app.camunda.com/nexus/content/groups/public/org/camunda/bpm/webapp/camunda-webapp-tomcat/7.1.0-Final/
and
http://docs.camunda.org/latest/guides/installation-guide/tomcat/).

Further informations:
My Spring-Config class looks like this:
@Configuration
public class TomcatConfig
{
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.setPort(8080);
return factory;
}
}

And this is my application class:
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application extends SpringBootServletInitializer
{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
return application.sources(Application.class);
}

public static void main(String... args)
{
ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
If you need more information please ask.
I hope anybody can help. Thank you for reading.
Greetings Tobias

Daniel Meyer

unread,
Apr 11, 2014, 3:05:20 AM4/11/14
to camunda-...@googlegroups.com
Hi Tobias,

what do you want to achieve? 

1) Do you want to combine the camunda webapplication with your custom application in order to build a single web application (war) that you can deploy to tomact?
2) Do you want to deploy two seperate applications each with their own embedded process engine pointing to the same database?
3) Do you want to deploy two sperate applications use a shared process engine object running as container service?

The simplest configuration is (2). In that case you install the camunda standalone web application http://docs.camunda.org/latest/guides/installation-guide/standalone/#installation and change the configuration of the process engine datasource to point to the same database you use in your custom application.

Regards,
Daniel


tob...@holke-online.net

unread,
Apr 22, 2014, 12:38:49 PM4/22/14
to camunda-...@googlegroups.com
Hi Daniel,

sorry for my late answer.

We solved the Problem by adding the following dependencies to pom.xml:
    <dependency>
            <groupId>org.camunda.bpm.webapp</groupId>
            <artifactId>camunda-webapp</artifactId>
            <version>${camunda.version}</version>
            <classifier>classes</classifier>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxrs</artifactId>
            <version>2.3.5.Final</version>
        </dependency>
        <dependency>
            <groupId>org.camunda.bpm.webapp</groupId>
            <artifactId>camunda-webapp</artifactId>
            <version>${camunda.version}</version>
            <type>war</type>
        </dependency>
Now we can use Cockpit and Tasklist in the embedded Tomcatserver from Spring. (Solution by Christoph Berg)

Greetings

Tobias

Daniel Meyer

unread,
Apr 23, 2014, 1:30:05 PM4/23/14
to camunda-...@googlegroups.com
Hi Tobi,

Glad to hear that.

As an additional side note: we now also provide a standalone distribution of the camunda webapp which embeds Spring and and the process engine:
Maybe you can also create a WAR overlay for that one. I am not sure

Regards,
Daniel Meyer

tob...@holke-online.net

unread,
Apr 23, 2014, 3:36:27 PM4/23/14
to camunda-...@googlegroups.com
Hi Daniel,

with that solution we would still need a single tomcat, or not?
With our solution we can package one single war-file which we can start with the java -jar command. Then Spring starts up the tomcat with the process engine, cockpit und tasklist. So we have no additional installation effort like a tomcat distribution.

Cheers 
Tobias

Daniel Meyer

unread,
Apr 23, 2014, 3:41:05 PM4/23/14
to camunda-...@googlegroups.com
Yes that is probably true. I have to admit that I am not really familiar
with Spring boot.

But it is great to hear that i works out for you!

Cheers,
Daniel

tob...@holke-online.net

unread,
Apr 30, 2014, 11:48:31 AM4/30/14
to camunda-...@googlegroups.com
I forgot to post the Configuration Bean. here is it: (Developed by Christoph Berg)
/**
 * Registriert die benötigten Beobachter, Filter und Servlets um die Camunda Webapplikationen zu nutzen.
 *
 * <p>Im Falle des eingebetteten Servletcontainers wird die bereitgestellte {@code web.xml} Datei der Camunda
 * Webapplkationen nicht berücksichtigt, so dass die benötigten Komponenten programmatisch registriert werden.</p>
 *
 * <p>Es ist darauf zu achten, dass die programmatische Registrierung mit jener aus der {@code web.xml}
 * übereinstimmt.</p>
 *
 * @author Christoph Berg
 */
@Component
public class CamundaWebAppInitializer implements ServletContextInitializer
{
    /**
     * Protokollinstanz dieser Klasse.
     */
    public static final Logger LOGGER = LoggerFactory.getLogger(CamundaWebAppInitializer.class);

    /**
     * Standardeinstellung, auf welcher Basis die Filter arbeiten sollen.
     */
    private static final EnumSet<DispatcherType> DISPATCHER_TYPES = EnumSet.of(DispatcherType.REQUEST);

    /**
     * Servlet Kontext, in dem zusätzliche Filter, Servlets, usw. registriert werden.
     */
    private ServletContext servletContext;

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException
    {
        this.servletContext = servletContext;

        // Beobachter zum Initialisieren der Webanwendung registrieren
        servletContext.addListener(new CockpitContainerBootstrap());
        servletContext.addListener(new AdminContainerBootstrap());

        // Filter registrieren
        registerFilter("Authentication Filter", AuthenticationFilter.class, "/*");

        HashMap<String, String> securityFilterParameters = new HashMap<>();
        securityFilterParameters.put("configFile", "/WEB-INF/securityFilterRules.json");
        registerFilter("Security Filter", SecurityFilter.class, securityFilterParameters, "/*");

        registerFilter("Cockpit Client Plugins Filter", CockpitClientPluginsFilter.class,
                "/app/cockpit/cockpit-bootstrap.js", "/app/cockpit/cockpit.js");

        registerFilter("Admin Client Plugins Filter", AdminClientPluginsFilter.class, "/app/admin/admin-bootstrap.js",
                "/app/admin/admin.js");

        registerFilter("Engines Filter", ProcessEnginesFilter.class, "/app/*");

        registerFilter("CacheControlFilter", CacheControlFilter.class, "/api/*");

        HashMap<String, String> cockpitApiParameters = new HashMap<>();
        cockpitApiParameters.put("javax.ws.rs.Application", "org.camunda.bpm.cockpit.impl.web.CockpitApplication");
        cockpitApiParameters.put("resteasy.servlet.mapping.prefix", "/api/cockpit");
        registerServlet("Cockpit Api", HttpServletDispatcher.class, cockpitApiParameters, "/api/cockpit/*");

        HashMap<String, String> adminApiParameters = new HashMap<>();
        adminApiParameters.put("javax.ws.rs.Application", "org.camunda.bpm.admin.impl.web.AdminApplication");
        adminApiParameters.put("resteasy.servlet.mapping.prefix", "/api/admin");
        registerServlet("Admin Api", HttpServletDispatcher.class, adminApiParameters, "/api/admin/*");

        HashMap<String, String> engineApiParameters = new HashMap<>();
        engineApiParameters.put("javax.ws.rs.Application", "org.camunda.bpm.webapp.impl.engine" +
                ".EngineRestApplication");
        engineApiParameters.put("resteasy.servlet.mapping.prefix", "/api/engine");
        registerServlet("Engine Api", HttpServletDispatcher.class, engineApiParameters, "/api/engine/*");
    }

    /**
     * Registriert einen Filter zur Ausführung, wenn die angegebenen URL Muster aufgerufen werden.
     *
     * <p>Ist der Filter bereits registriert, wird die zugehörige Registrierungsinformation zurückgeliefert.</p>
     *
     * @param filterName  Name, unter welchem der Filter nachgeschlagen werden kann
     * @param filterClass Klasse, die die Logik des Filters enthält
     * @param urlPatterns Muster, auf welche eine aufgerufene URL passen muss, damit der Filter ausgeführt wird
     *
     * @return Registrierungsinformationen des Filters
     */
    private FilterRegistration registerFilter(final String filterName,
                                              final Class<? extends Filter> filterClass,
                                              final String... urlPatterns)
    {
        return registerFilter(filterName, filterClass, null, urlPatterns);
    }

    /**
     * Registriert einen Filter zur Ausführung, wenn die angegebenen URL Muster aufgerufen werden.
     *
     * <p>Ist der Filter bereits registriert, wird die zugehörige Registrierungsinformation zurückgeliefert.</p>
     *
     * @param filterName     Name, unter welchem der Filter nachgeschlagen werden kann
     * @param filterClass    Klasse, die die Logik des Filters enthält
     * @param initParameters Parameter, welche dem Filter zur Initialisierung übergeben werden
     * @param urlPatterns    Muster, auf welche eine aufgerufene URL passen muss, damit der Filter ausgeführt wird
     *
     * @return Registrierungsinformationen des Filters
     */
    private FilterRegistration registerFilter(final String filterName,
                                              final Class<? extends Filter> filterClass,
                                              final Map<String, String> initParameters,
                                              final String... urlPatterns)
    {
        FilterRegistration filterRegistration = servletContext.getFilterRegistration(filterName);

        if (filterRegistration == null)
        {
            filterRegistration = servletContext.addFilter(filterName, filterClass);
            filterRegistration.addMappingForUrlPatterns(DISPATCHER_TYPES, true, urlPatterns);

            if (initParameters != null)
            {
                filterRegistration.setInitParameters(initParameters);
            }

            LOGGER.debug("Filter {} für URL Pfade {} registriert", filterName, urlPatterns);
        }

        return filterRegistration;
    }

    /**
     * Registriert ein Servlet zur Ausführung, wenn die angegebenen URL Muster aufgerufen werden.
     *
     * <p>Ist das Servlet bereits registriert, wird die zugehörige Registrierungsinformation zurückgeliefert.</p>
     *
     * @param servletName    Name, unter welchem das Servlet nachgeschlagen werden kann
     * @param servletClass   Klasse, die die Logik des Servlets enthält
     * @param initParameters Parameter, welche dem Servlet zur Initialisierung übergeben werden
     * @param urlPatterns    Muster, auf welche eine aufgerufene URL passen muss, damit das Servlet ausgeführt wird
     *
     * @return Registrierungsinformationen des Servlets
     */
    private ServletRegistration registerServlet(final String servletName, final Class<? extends Servlet>
            servletClass, final Map<String, String> initParameters, final String... urlPatterns)
    {
        ServletRegistration servletRegistration = servletContext.getServletRegistration(servletName);

        if (servletRegistration == null)
        {
            servletRegistration = servletContext.addServlet(servletName, servletClass);
            servletRegistration.addMapping(urlPatterns);
            servletRegistration.setInitParameters(initParameters);

            LOGGER.debug("Servlet {} für URL Pfade {} registriert.", servletName, urlPatterns);
        }

        return servletRegistration;
    }
}


 

tob...@holke-online.net

unread,
Apr 30, 2014, 11:57:59 AM4/30/14
to camunda-...@googlegroups.com
I have also a new interesting error when I startup the engine with a process. Please look at the attached file.
I tried to delete those bpmn process-files. It helped, but the process is ignored while the deployment.
As a test i deployed the process at a standard tomcat with camunda bpm engine and it works fine.
 
 Maybe someone can give us help?

Cheers 
Tobias
 
console.txt

Daniel Meyer

unread,
May 5, 2014, 4:28:14 AM5/5/14
to camunda-...@googlegroups.com
Hi Tobias,

Seems like the process

 sepia.war!assets/vendor/camunda-bpmn.js/test/resources/complex-waitstates-subprocesses.bpmn 

is not ready to be deployed to the process engine. Maybe you can simply remove it? I suppose that it is an example process of camunda-bpmn.js and is now somehow found by the scanner. 

Daniel

tob...@holke-online.net

unread,
May 5, 2014, 6:01:47 AM5/5/14
to camunda-...@googlegroups.com
Hi Daniel,

i tried this.
When I remove it, my own process is found by the engine, but is not deployed because of missing resources in my module.
But there ist resource file (CheckMails.bpmn). 
I attached the console output, theprocesses.xml and my BPMN file.

Cheers Tobias

console2.txt
CheckMails.bpmn
processes.xml

tob...@holke-online.net

unread,
May 7, 2014, 11:56:43 AM5/7/14
to camunda-...@googlegroups.com
I solved the problem:

I needed to add the following tag to my dependency:
  <dependency>
            <groupId>com.trustpact.sepia.modules</groupId>
            <artifactId>mail-checkout</artifactId>
            <version>1.0-SNAPSHOT</version>
            <type>war</type>
 </dependency>

The Tag 'type' is essential to get it working. After this the bpmn file is found by the system.

Cheers Tobias
Reply all
Reply to author
Forward
0 new messages