This is an automated email from the ASF dual-hosted git repository.
jbonofre pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karaf.git
The following commit(s) were added to refs/heads/main by this push:
new e02e22b05 fix(#656): Register CXF servlet via OSGi Servlet Whiteboard
to restore service listing page (#687)
e02e22b05 is described below
commit e02e22b05190a92f61020344ce7bc6eb28de0fa1
Author: JB Onofré <[email protected]>
AuthorDate: Thu Mar 12 15:50:02 2026 +0100
fix(#656): Register CXF servlet via OSGi Servlet Whiteboard to restore
service listing page (#687)
The CXF "Available SOAP Services" listing page was unavailable because
HttpService was removed in OSGi 8. Replace the defunct HttpService-based
servlet registration with the OSGi Servlet Whiteboard pattern, which
registers the CXFNonSpringServlet as an OSGi service with whiteboard
properties picked up by pax-web. Add http-whiteboard feature dependency
to camel-cxf.
---
.../http/osgi/HTTPTransportActivator.java | 29 +++---
.../http/osgi/HttpServiceTrackerCust.java | 70 -------------
.../cxf/transport/http/osgi/ServletExporter.java | 109 +++++++++------------
features/src/main/feature/camel-features.xml | 1 +
4 files changed, 68 insertions(+), 141 deletions(-)
diff --git
a/components/camel-cxf/camel-cxf-all/src/main/java/org/apache/camel/component/cxf/transport/http/osgi/HTTPTransportActivator.java
b/components/camel-cxf/camel-cxf-all/src/main/java/org/apache/camel/component/cxf/transport/http/osgi/HTTPTransportActivator.java
index 1586c3913..663ef466f 100644
---
a/components/camel-cxf/camel-cxf-all/src/main/java/org/apache/camel/component/cxf/transport/http/osgi/HTTPTransportActivator.java
+++
b/components/camel-cxf/camel-cxf-all/src/main/java/org/apache/camel/component/cxf/transport/http/osgi/HTTPTransportActivator.java
@@ -17,23 +17,27 @@
package org.apache.camel.component.cxf.transport.http.osgi;
+import jakarta.servlet.Servlet;
import org.apache.cxf.common.util.CollectionUtils;
import org.apache.cxf.common.util.PropertyUtils;
import org.apache.cxf.transport.http.DestinationRegistry;
import org.apache.cxf.transport.http.DestinationRegistryImpl;
import org.apache.cxf.transport.http.HTTPConduitConfigurer;
import org.apache.cxf.transport.http.HTTPTransportFactory;
+import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedService;
import org.osgi.service.cm.ManagedServiceFactory;
-import org.osgi.service.http.HttpService;
-import org.osgi.util.tracker.ServiceTracker;
public class HTTPTransportActivator implements BundleActivator {
+ private static final String CXF_CONFIG_PID = "org.apache.cxf.osgi";
private static final String DISABLE_DEFAULT_HTTP_TRANSPORT =
"org.apache.cxf.osgi.http.transport.disable";
- private ServiceTracker<HttpService, ?> httpServiceTracker;
+
+ private ServiceRegistration<ManagedService> servletPublisherReg;
+ private ServletExporter servletExporter;
@Override
public void start(final BundleContext context) throws Exception {
@@ -46,18 +50,18 @@ public class HTTPTransportActivator implements
BundleActivator {
"org.apache.cxf.http.conduit-configurer");
if
(PropertyUtils.isTrue(context.getProperty(DISABLE_DEFAULT_HTTP_TRANSPORT))) {
- //TODO: Review if it also makes sense to support
"http.transport.disable"
- // directly in the CXF_CONFIG_SCOPE properties file
return;
}
DestinationRegistry destinationRegistry = new
DestinationRegistryImpl();
HTTPTransportFactory transportFactory = new
HTTPTransportFactory(destinationRegistry);
- // HttpService is no longer available in OSGI 8
-// HttpServiceTrackerCust customizer = new
HttpServiceTrackerCust(destinationRegistry, context);
-// httpServiceTracker = new ServiceTracker<>(context,
HttpService.class, customizer);
-// httpServiceTracker.open();
+ // Register the CXF servlet using OSGi Servlet Whiteboard
+ Servlet servlet = new CXFNonSpringServlet(destinationRegistry, false);
+ servletExporter = new ServletExporter(servlet, context);
+ servletPublisherReg = context.registerService(ManagedService.class,
+ servletExporter,
+ CollectionUtils.singletonDictionary(Constants.SERVICE_PID,
CXF_CONFIG_PID));
context.registerService(DestinationRegistry.class.getName(),
destinationRegistry, null);
context.registerService(HTTPTransportFactory.class.getName(),
transportFactory, null);
@@ -71,8 +75,11 @@ public class HTTPTransportActivator implements
BundleActivator {
@Override
public void stop(BundleContext context) throws Exception {
- if (httpServiceTracker != null) {
- httpServiceTracker.close();
+ if (servletPublisherReg != null) {
+ servletPublisherReg.unregister();
+ }
+ if (servletExporter != null) {
+ servletExporter.destroy();
}
}
}
diff --git
a/components/camel-cxf/camel-cxf-all/src/main/java/org/apache/camel/component/cxf/transport/http/osgi/HttpServiceTrackerCust.java
b/components/camel-cxf/camel-cxf-all/src/main/java/org/apache/camel/component/cxf/transport/http/osgi/HttpServiceTrackerCust.java
deleted file mode 100644
index 125526a56..000000000
---
a/components/camel-cxf/camel-cxf-all/src/main/java/org/apache/camel/component/cxf/transport/http/osgi/HttpServiceTrackerCust.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * 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.camel.component.cxf.transport.http.osgi;
-
-import jakarta.servlet.Servlet;
-import org.apache.cxf.common.util.CollectionUtils;
-import org.apache.cxf.transport.http.DestinationRegistry;
-import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedService;
-import org.osgi.service.http.HttpService;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-final class HttpServiceTrackerCust implements
ServiceTrackerCustomizer<HttpService, HttpService> {
- private static final String CXF_CONFIG_PID = "org.apache.cxf.osgi";
- private final DestinationRegistry destinationRegistry;
- private final BundleContext context;
- private ServiceRegistration<ManagedService> servletPublisherReg;
- private ServletExporter servletExporter;
-
- HttpServiceTrackerCust(DestinationRegistry destinationRegistry,
BundleContext context) {
- this.destinationRegistry = destinationRegistry;
- this.context = context;
- }
-
- @Override
- public void removedService(ServiceReference<HttpService> reference,
HttpService service) {
- servletPublisherReg.unregister();
- try {
- servletExporter.updated(null);
- } catch (ConfigurationException e) {
- // Ignore
- }
- }
-
- @Override
- public void modifiedService(ServiceReference<HttpService> reference,
HttpService service) {
- }
-
- @Override
- public HttpService addingService(ServiceReference<HttpService> reference) {
- HttpService httpService = context.getService(reference);
- Servlet servlet = new CXFNonSpringServlet(destinationRegistry, false);
- servletExporter = new ServletExporter(servlet, httpService);
- servletPublisherReg = context.registerService(ManagedService.class,
- servletExporter,
- CollectionUtils.singletonDictionary(Constants.SERVICE_PID,
- CXF_CONFIG_PID));
- return httpService;
- }
-}
diff --git
a/components/camel-cxf/camel-cxf-all/src/main/java/org/apache/camel/component/cxf/transport/http/osgi/ServletExporter.java
b/components/camel-cxf/camel-cxf-all/src/main/java/org/apache/camel/component/cxf/transport/http/osgi/ServletExporter.java
index 4f854d4b6..dd4cbbb12 100644
---
a/components/camel-cxf/camel-cxf-all/src/main/java/org/apache/camel/component/cxf/transport/http/osgi/ServletExporter.java
+++
b/components/camel-cxf/camel-cxf-all/src/main/java/org/apache/camel/component/cxf/transport/http/osgi/ServletExporter.java
@@ -18,116 +18,105 @@
package org.apache.camel.component.cxf.transport.http.osgi;
import java.util.Dictionary;
-import java.util.Enumeration;
+import java.util.Hashtable;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.servlet.Servlet;
import org.apache.cxf.common.logging.LogUtils;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
-import org.osgi.service.http.HttpContext;
-import org.osgi.service.http.HttpService;
class ServletExporter implements ManagedService {
protected static final Logger LOG =
LogUtils.getL7dLogger(ServletExporter.class);
private static final String CXF_SERVLET_PREFIX = "org.apache.cxf.servlet.";
- private String alias;
private final Servlet servlet;
- private ServiceRegistration<?> serviceRegistration;
- private final HttpService httpService;
+ private final BundleContext bundleContext;
+ private ServiceRegistration<Servlet> servletServiceRegistration;
- ServletExporter(Servlet servlet, HttpService httpService) {
+ ServletExporter(Servlet servlet, BundleContext bundleContext) {
this.servlet = servlet;
- this.httpService = httpService;
+ this.bundleContext = bundleContext;
}
@SuppressWarnings("rawtypes")
@Override
public void updated(Dictionary properties) throws ConfigurationException {
- if (alias != null) {
+ if (servletServiceRegistration != null) {
try {
- LOG.log(Level.INFO, "Unregistering previous instance of \"" +
alias + "\" servlet");
- httpService.unregister(alias);
- } catch (IllegalArgumentException e) {
- // NOTE: pax-web specific...
- if (e.getMessage() != null && e.getMessage().contains("was
never registered")) {
- LOG.log(Level.INFO, "CXF OSGi servlet was not
unregistered: " + e.getMessage());
- } else {
- LOG.log(Level.SEVERE, e.getMessage(), e);
- }
+ LOG.log(Level.INFO, "Unregistering previous CXF servlet");
+ servletServiceRegistration.unregister();
+ } catch (IllegalStateException e) {
+ LOG.log(Level.FINE, "CXF OSGi servlet was already
unregistered: " + e.getMessage());
}
+ servletServiceRegistration = null;
if (properties == null) {
- // we're simply stopping. if we couldn't unregister, that
means we had to little time to register
- // otherwise, we'll try to register the servlet
return;
}
- alias = null;
}
if (properties == null) {
properties = new Properties();
}
- Properties sprops = new Properties();
- sprops.put("init-prefix",
- getProp(properties, CXF_SERVLET_PREFIX + "init-prefix", ""));
- sprops.put("servlet-name",
- getProp(properties, CXF_SERVLET_PREFIX + "name",
"cxf-osgi-transport-servlet"));
- sprops.put("hide-service-list-page",
+
+ String context = (String) getProp(properties, CXF_SERVLET_PREFIX +
"context", "/cxf");
+ String servletName = (String) getProp(properties, CXF_SERVLET_PREFIX +
"name", "cxf-osgi-transport-servlet");
+
+ // Build Servlet Whiteboard service properties
+ Hashtable<String, Object> whiteboardProps = new Hashtable<>();
+ whiteboardProps.put("osgi.http.whiteboard.servlet.name", servletName);
+ whiteboardProps.put("osgi.http.whiteboard.servlet.pattern", context +
"/*");
+ whiteboardProps.put("osgi.http.whiteboard.servlet.async-supported",
+ Boolean.valueOf(getProp(properties, CXF_SERVLET_PREFIX +
"async-supported", "true").toString()));
+
+ // Pass CXF servlet init parameters
+ whiteboardProps.put("servlet.init.hide-service-list-page",
getProp(properties, CXF_SERVLET_PREFIX +
"hide-service-list-page", "false"));
- sprops.put("disable-address-updates",
+ whiteboardProps.put("servlet.init.disable-address-updates",
getProp(properties, CXF_SERVLET_PREFIX +
"disable-address-updates", "true"));
- sprops.put("base-address",
+ whiteboardProps.put("servlet.init.base-address",
getProp(properties, CXF_SERVLET_PREFIX + "base-address", ""));
- sprops.put("service-list-path",
+ whiteboardProps.put("servlet.init.service-list-path",
getProp(properties, CXF_SERVLET_PREFIX + "service-list-path",
""));
- sprops.put("static-resources-list",
+ whiteboardProps.put("servlet.init.static-resources-list",
getProp(properties, CXF_SERVLET_PREFIX +
"static-resources-list", ""));
- sprops.put("redirects-list",
+ whiteboardProps.put("servlet.init.redirects-list",
getProp(properties, CXF_SERVLET_PREFIX + "redirects-list",
""));
- sprops.put("redirect-servlet-name",
+ whiteboardProps.put("servlet.init.redirect-servlet-name",
getProp(properties, CXF_SERVLET_PREFIX +
"redirect-servlet-name", ""));
- sprops.put("redirect-servlet-path",
+ whiteboardProps.put("servlet.init.redirect-servlet-path",
getProp(properties, CXF_SERVLET_PREFIX +
"redirect-servlet-path", ""));
- sprops.put("service-list-all-contexts",
+ whiteboardProps.put("servlet.init.service-list-all-contexts",
getProp(properties, CXF_SERVLET_PREFIX +
"service-list-all-contexts", ""));
- sprops.put("service-list-page-authenticate",
+ whiteboardProps.put("servlet.init.service-list-page-authenticate",
getProp(properties, CXF_SERVLET_PREFIX +
"service-list-page-authenticate", "false"));
- sprops.put("service-list-page-authenticate-realm",
+
whiteboardProps.put("servlet.init.service-list-page-authenticate-realm",
getProp(properties, CXF_SERVLET_PREFIX +
"service-list-page-authenticate-realm", "karaf"));
- sprops.put("use-x-forwarded-headers",
+ whiteboardProps.put("servlet.init.use-x-forwarded-headers",
getProp(properties, CXF_SERVLET_PREFIX +
"use-x-forwarded-headers", "false"));
- sprops.put("async-supported",
- getProp(properties, CXF_SERVLET_PREFIX + "async-supported",
"true"));
-
- // Accept extra properties by default, can be disabled if it is really
needed
- if (Boolean.valueOf(getProp(properties, CXF_SERVLET_PREFIX +
"support.extra.properties", "true").toString())) {
- Enumeration keys = properties.keys();
- while (keys.hasMoreElements()) {
- String nextKey = keys.nextElement().toString();
- if (!nextKey.startsWith(CXF_SERVLET_PREFIX)) {
- sprops.put(nextKey, properties.get(nextKey));
- }
- }
- }
-
- if (serviceRegistration != null) {
- serviceRegistration.unregister();
- }
- alias = (String)getProp(properties, CXF_SERVLET_PREFIX + "context",
"/cxf");
- HttpContext context = httpService.createDefaultHttpContext();
try {
- LOG.log(Level.INFO, "Registering new instance of \"" + alias + "\"
servlet");
- // TODO: use the registerServlet method when upgrading to OSGI
CMPN 8
-// httpService.registerServlet(alias, servlet, sprops, context);
+ LOG.log(Level.INFO, "Registering CXF servlet on " + context + "
via Servlet Whiteboard");
+ servletServiceRegistration =
bundleContext.registerService(Servlet.class, servlet, whiteboardProps);
} catch (Exception e) {
LOG.log(Level.WARNING, "Error registering CXF OSGi servlet " +
e.getMessage(), e);
}
}
+ void destroy() {
+ if (servletServiceRegistration != null) {
+ try {
+ servletServiceRegistration.unregister();
+ } catch (IllegalStateException e) {
+ // already unregistered
+ }
+ servletServiceRegistration = null;
+ }
+ }
+
@SuppressWarnings("rawtypes")
private Object getProp(Dictionary properties, String key, Object
defaultValue) {
Object value = properties.get(key);
diff --git a/features/src/main/feature/camel-features.xml
b/features/src/main/feature/camel-features.xml
index 27c827b0b..4e9e6e27c 100644
--- a/features/src/main/feature/camel-features.xml
+++ b/features/src/main/feature/camel-features.xml
@@ -938,6 +938,7 @@
<feature version='${camel-osgi-version-range}'>camel-spring</feature>
<feature
version="${camel-osgi-jakarta-annotation2-version}">jakarta-annotation</feature>
<feature version="[6,7)">jakarta-servlet</feature>
+ <feature>http-whiteboard</feature>
<feature version="[3,4)">jakarta-validation</feature>
<feature
version="${camel-osgi-saaj-version}">jakarta-soap-implementation</feature>
<bundle
dependency="true">mvn:org.glassfish.hk2/osgi-resource-locator/${osgi-resource-locator-version}</bundle>