diff --git a/org.eclipse.osgitech.rest.jetty/pom.xml b/org.eclipse.osgitech.rest.jetty/pom.xml index 49a54f6..93cd445 100644 --- a/org.eclipse.osgitech.rest.jetty/pom.xml +++ b/org.eclipse.osgitech.rest.jetty/pom.xml @@ -74,6 +74,10 @@ org.apache.felix org.apache.felix.http.jetty + + org.crac + crac + @@ -117,6 +121,27 @@ + + biz.aQute.bnd + bnd-maven-plugin + true + + + jar + + jar + + + + + + + biz.aQute.bnd bnd-resolver-maven-plugin diff --git a/org.eclipse.osgitech.rest.jetty/src/main/java/org/eclipse/osgitech/rest/jetty/JettyBackedWhiteboardComponent.java b/org.eclipse.osgitech.rest.jetty/src/main/java/org/eclipse/osgitech/rest/jetty/JettyBackedWhiteboardComponent.java index 9775122..90e6ead 100644 --- a/org.eclipse.osgitech.rest.jetty/src/main/java/org/eclipse/osgitech/rest/jetty/JettyBackedWhiteboardComponent.java +++ b/org.eclipse.osgitech.rest.jetty/src/main/java/org/eclipse/osgitech/rest/jetty/JettyBackedWhiteboardComponent.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2012 - 2022 Data In Motion and others. + * Copyright (c) 2012 - 2024 Data In Motion and others. * All rights reserved. * * This program and the accompanying materials are made available under the terms of the @@ -10,6 +10,7 @@ * Data In Motion - initial API and implementation * Stefan Bishof - API and implementation * Tim Ward - implementation + * Dirk Fauth - add CRaC support */ package org.eclipse.osgitech.rest.jetty; @@ -62,6 +63,10 @@ public class JettyBackedWhiteboardComponent { Logger logger = Logger.getLogger(JettyBackedWhiteboardComponent.class.getName()); private JerseyServiceRuntime serviceRuntime; + + // need to keep a strong reference to avoid that the resource gets garbage collected + @SuppressWarnings("unused") + private JettyCracResource cracHandler; public enum State { INIT, STARTED, STOPPED, EXCEPTION @@ -93,6 +98,17 @@ public void activate(BundleContext context, Map properties) thro serviceRuntime.start(getServiceRuntimeProperties(properties)); + + try { + Class.forName("org.crac.Resource"); + + // org.crac.Resource was found, so we create an instance of the JettyCracResource + cracHandler = new JettyCracResource(this); + } catch (ClassNotFoundException e) { + // org.crac.Resource could not be found + // we simply do nothing, as CRaC support is not available + } + } private Map getServiceRuntimeProperties(Map properties) { @@ -348,4 +364,12 @@ private void stopServer() { logger.log(Level.SEVERE, "Error stopping Jetty server", e); } } + + /** + * + * @return the Jetty server managed by this class. Can be null. + */ + Server getJettyServer() { + return jettyServer; + } } diff --git a/org.eclipse.osgitech.rest.jetty/src/main/java/org/eclipse/osgitech/rest/jetty/JettyCracResource.java b/org.eclipse.osgitech.rest.jetty/src/main/java/org/eclipse/osgitech/rest/jetty/JettyCracResource.java new file mode 100644 index 0000000..6f41ff2 --- /dev/null +++ b/org.eclipse.osgitech.rest.jetty/src/main/java/org/eclipse/osgitech/rest/jetty/JettyCracResource.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2024 Dirk Fauth and others. + * All rights reserved. + * + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v20.html + * + * Contributors: + * Dirk Fauth - initial API and implementation + */ +package org.eclipse.osgitech.rest.jetty; + +import java.util.Arrays; + +import org.crac.Context; +import org.crac.Core; +import org.crac.Resource; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.util.component.LifeCycle; + +/** + * This class is used to add CRaC support to the jetty bundle by using the + * org.crac API. It adapts the examples and best practices from the + * CRaC documentation and the examples. + * + * @see `org.crac` API + * @see Implementing + * Resource as Inner Class + * @see Step-by-step + * CRaC support for a Jetty app + * @see CRaC + * example-jetty + */ +public class JettyCracResource { + + // the org.crac.Resource is implemented as an inner class and kept as a strong + // reference to avoid that it is garbage collected after the registration. + private Resource cracHandler; + + public JettyCracResource(JettyBackedWhiteboardComponent jettyComponent) { + cracHandler = new Resource() { + @Override + public void beforeCheckpoint(Context context) { + Server jettyServer = jettyComponent.getJettyServer(); + if (jettyServer != null && !jettyServer.isStopped()) { + // Stop the connectors only and keep the expensive application running + Arrays.asList(jettyServer.getConnectors()).forEach(c -> LifeCycle.stop(c)); + } + } + + @Override + public void afterRestore(Context context) { + Server jettyServer = jettyComponent.getJettyServer(); + if (jettyServer != null && !jettyServer.isStopped()) { + Arrays.asList(jettyServer.getConnectors()).forEach(c -> LifeCycle.start(c)); + } + } + }; + Core.getGlobalContext().register(cracHandler); + } +} diff --git a/pom.xml b/pom.xml index f5c3e49..8c06386 100644 --- a/pom.xml +++ b/pom.xml @@ -69,6 +69,7 @@ 9.5 2.15.2 1.1.5 + 1.5.0 @@ -464,6 +465,12 @@ biz.aQute.bnd.annotation 6.4.0 + + org.crac + crac + ${crac.version} + provided +