javajettyosgiapache-karafpax-web

OPS4J Pax Web / Apache Karaf: Get dynamically selected HTTP port at runtime


Problem:
I'm trying to get the dynamically selected HTTP port from OPS4J Pax Web within my application code at runtime.

Setup:
I have a custom Apache Karaf 4.4.0 distribution that installs the http Karaf Feature as a boot feature. The http Karaf Feature uses the OPS4J Pax Web implementation of the Http Service Specification with a Jetty web server. According to the Pax Web User Guide, the property org.osgi.service.http.port in the configuration file org.ops4j.pax.web.cfg has been set to 0 so that Pax Web automatically selects an HTTP port. This part works as expected.

Investigations:
I have tried the following approaches to read the HTTP port at runtime from different sources. Unfortunately, I wasn't successful with any of them.

  1. Reading the property org.osgi.service.http.port from the configuration file org.ops4j.pax.web.cfg via the ConfigurationAdmin service resulted in the value 0.

  2. Reading the HTTP port via an injected HttpService (@Reference HttpService ...) didn't work because the HttpService does not provide a method to get the HTTP port.

  3. Reading the HTTP port via an injected WebContainer service from Pax Web (@Reference WebContainer ...) didn't work because the WebContainer service does not provide a method to get the HTTP port.

Current workaround:
As a current workaround, I set the property org.osgi.service.http.port in the configuration file org.ops4j.pax.web.cfg for the root Karaf Container to a fixed value. For all child Karaf Containers, the property is commented out and the HTTP port is selected by a small code snippet and passed as a JVM argument before the child Karaf Containers are started via the InstanceService. This allows me to read the HTTP port as a system property (System.getProperty(...)) in my application code.

However, I would like to make use of the possibility to let Pax Web automatically select an HTTP port, so maybe someone knows how the get the dynamically selected HTTP port at runtime.

Many thanks in advance.

Solution:
Thanks to Grzegorz Grzybek, I managed to get the dynamically selected HTTP port at runtime with the following code snippet:

@Reference
private HttpServiceRuntime httpServiceRuntime;
...
Map<String, Object> properties = httpServiceRuntime.getRuntimeDTO().serviceDTO.properties;
String[] localHttpEndpoints = (String[]) properties.get(HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT);
URL localHttpEndpointUrl = new URL(localHttpEndpoints[0]);
int httpPort = localHttpEndpointUrl.getPort();

Solution

  • In Pax Web 8 (available since Karaf 4.4.0) you can grab an instance of org.osgi.service.http.runtime.HttpServiceRuntime service and check its standard osgi.http.endpoint property. In my case it was:

    objectClass = [org.osgi.service.http.runtime.HttpServiceRuntime]
    osgi.http.endpoint = [http://0.0.0.0:44067/]
    osgi.http.service.id = [107]
    service.bundleid = 70
    service.changecount = 0
    service.id = 108
    service.scope = singleton
    

    while the PID property was 0:

    karaf@root()> property-list --pid org.ops4j.pax.web
       felix.fileinstall.filename = file:/data/servers/apache-karaf-4.4.1/etc/org.ops4j.pax.web.cfg
       javax.servlet.context.tempdir = /data/servers/apache-karaf-4.4.1/data/pax-web/tmp
       org.apache.karaf.features.configKey = org.ops4j.pax.web
       org.osgi.service.http.enabled = true
       org.osgi.service.http.port = 0
       org.osgi.service.http.secure.enabled = false