From ad855589d05add7afa6470a9118ebad9e516ed2e Mon Sep 17 00:00:00 2001 From: Gregor Eichelberger Date: Tue, 30 Jan 2024 20:00:36 +0100 Subject: [PATCH] DOSGi Cellar example --- .../src/main/feature/feature.xml | 5 +- etc/hazelcast.xml | 216 ++++++++++++++++++ etc/org.apache.karaf.cellar.groups.cfg | 62 +++++ etc/org.apache.karaf.cellar.node.cfg | 47 ++++ modules/hello-world-endpoint-dosgi/pom.xml | 84 +++++++ .../impl/endpoint/HelloWorldRestEndpoint.java | 160 +++++++++++++ modules/hello-world-impl/pom.xml | 4 + .../impl/HelloWorldServiceImpl.java | 3 +- pom.xml | 2 + 9 files changed, 581 insertions(+), 2 deletions(-) create mode 100644 etc/hazelcast.xml create mode 100644 etc/org.apache.karaf.cellar.groups.cfg create mode 100644 etc/org.apache.karaf.cellar.node.cfg create mode 100644 modules/hello-world-endpoint-dosgi/pom.xml create mode 100644 modules/hello-world-endpoint-dosgi/src/main/java/org/opencastproject/helloworld/impl/endpoint/HelloWorldRestEndpoint.java diff --git a/assemblies/karaf-features/src/main/feature/feature.xml b/assemblies/karaf-features/src/main/feature/feature.xml index 68e59b4310f..5ff7089339b 100644 --- a/assemblies/karaf-features/src/main/feature/feature.xml +++ b/assemblies/karaf-features/src/main/feature/feature.xml @@ -1,6 +1,8 @@ + mvn:org.apache.karaf.cellar/apache-karaf-cellar/${karaf.cellar.version}/xml/features + mvn:com.google.guava/guava/${guava.version} mvn:com.google.guava/failureaccess/${failureaccess.version} @@ -19,6 +21,8 @@ scr cxf-jaxrs cxf-http-jetty + cellar + cellar-dosgi mvn:org.apache.httpcomponents/httpclient-osgi/${httpcomponents-httpclient.version} @@ -147,7 +151,6 @@ opencast-core opencast-services-processing-heavy-load opencast-services-processing-light-load - mvn:org.opencastproject/opencast-admin-ui/${project.version} mvn:org.opencastproject/opencast-admin-ui-frontend/${project.version} mvn:org.opencastproject/opencast-admin-ui-interface/${project.version} diff --git a/etc/hazelcast.xml b/etc/hazelcast.xml new file mode 100644 index 00000000000..866f0cafbb6 --- /dev/null +++ b/etc/hazelcast.xml @@ -0,0 +1,216 @@ + + + + cellar + pass + + http://localhost:8080/mancenter + + 5701 + + + 0 + + + + 224.2.2.3 + 54327 + + + 127.0.0.1 + + + my-access-key + my-secret-key + + us-west-1 + + ec2.amazonaws.com + + hazelcast-sg + type + hz-nodes + + + + 10.10.1.* + + + + + + PBEWithMD5AndDES + + thesalt + + thepass + + 19 + + + + + 16 + + 0 + + + + 0 + + 1 + + 0 + -1 + + + + + BINARY + + 1 + + 0 + + 0 + + 0 + + NONE + + 0 + + 25 + + com.hazelcast.map.merge.PassThroughMergePolicy + + + 0 + 0 + LRU + 5000 + 25 + 0 + + + + 1 + SET + + + + 1 + SET + + + + 1 + + + + 1 + + + + 0 + + 0 + 0 + 1000 + true + CANCEL_RUNNING_OPERATION + + + + 0 + 1 + 0 + + + + 0 + + + + + + 60 + 120 + + \ No newline at end of file diff --git a/etc/org.apache.karaf.cellar.groups.cfg b/etc/org.apache.karaf.cellar.groups.cfg new file mode 100644 index 00000000000..db4f83c4846 --- /dev/null +++ b/etc/org.apache.karaf.cellar.groups.cfg @@ -0,0 +1,62 @@ +# +# This property stores the cluster groups for which the local node is member +# +groups = default + +# +# Filtering of the bundles in the default cluster group +# +default.bundle.whitelist.inbound=* +default.bundle.whitelist.outbound=* +default.bundle.blacklist.inbound=*.xml +default.bundle.blacklist.outbound=*.xml + +# +# Filtering of the configurations in the default cluster group +# +default.config.whitelist.inbound=* +default.config.whitelist.outbound=* +default.config.blacklist.inbound=org.apache.felix.fileinstall*, \ + org.apache.karaf.management, \ + org.apache.karaf.shell, \ + org.ops4j.pax.web, \ + org.apache.aries.transaction, \ + org.ops4j.pax.logging, \ + org.apache.karaf.cellar.node, \ + org.apache.karaf.cellar.groups +default.config.blacklist.outbound=org.apache.felix.fileinstall*, \ + org.apache.karaf.management, \ + org.apache.karaf.shell, \ + org.ops4j.pax.web, \ + org.apache.aries.transaction, \ + org.ops4j.pax.logging, \ + org.apache.karaf.cellar.node, \ + org.apache.karaf.cellar.groups + +# +# Filtering of the features in the default cluster group +# +default.feature.whitelist.inbound=* +default.feature.whitelist.outbound=* +default.feature.blacklist.inbound=none +default.feature.blacklist.outbound=none + +# +# The following properties define the behavior to use when the node joins the cluster (the usage of the bootstrap +# synchronizer), per cluster group and per resource. +# The following values are accepted: +# disabled: means that the synchronizer doesn't sync cluster group and node states +# cluster: the synchronizer retrieves the state from the cluster group first (pull first), and push the node the state +# to the cluster group after (push after) +# node: the synchronizer push the node state to the cluster group (push first), and pull the state from the cluster group +# after (pull after) +# clusterOnly: the cluster is the "master", the node only retrieves and applies the cluster group state, nothing is +# pushed to the cluster group +# nodeOnly: the node is the "master", the node pushes his state to the cluster group, nothing is pulled from the +# cluster group +# +default.bundle.sync=disabled +default.config.sync=disabled +default.feature.sync=disabled +default.obr.urls.sync=disabled +default.balanced.servlet.sync=disabled diff --git a/etc/org.apache.karaf.cellar.node.cfg b/etc/org.apache.karaf.cellar.node.cfg new file mode 100644 index 00000000000..5a096610a83 --- /dev/null +++ b/etc/org.apache.karaf.cellar.node.cfg @@ -0,0 +1,47 @@ +# +# This node is member of the following cluster groups +# +groups = default + +# +# The following properties define if the local event listeners (per resource) +# A local listener listens for local events (like bundle install, etc) and broadcast this state change to the cluster +# +bundle.listener = false +config.listener = false +feature.listener = false + +# +# Cluster event producer +# +producer = true + +# +# Cluster event consumer +# +consumer = true + +# +# Cluster event handlers +# +# bundle event handler +handler.org.apache.karaf.cellar.bundle.BundleEventHandler = true +# config event handler +handler.org.apache.karaf.cellar.config.ConfigurationEventHandler = true +# feature event handler +handler.org.apache.karaf.cellar.features.FeaturesEventHandler = true +# DOSGi event handler +handler.org.apache.karaf.cellar.dosgi.RemoteServiceCallHandler = true +# OSGi event handler +handler.org.apache.karaf.cellar.event.ClusterEventHandler = true +# OBR event handler +handler.org.apache.karaf.cellar.obr.ObrBundleEventHandler = true +handler.org.apache.karaf.cellar.obr.ObrUrlEventHandler = true +# HTTP balancer event handler +handler.org.apache.karaf.cellar.http.balancer.BalancerEventHandler = true + +# +# Excluded config properties from the sync +# Some config properties can be considered as local to a node, and should not be sync on the cluster. +# +config.excluded.properties = felix.fileinstall.filename, felix.fileinstall.dir, felix.fileinstall.tmpdir, org.ops4j.pax.url.mvn.defaultRepositories diff --git a/modules/hello-world-endpoint-dosgi/pom.xml b/modules/hello-world-endpoint-dosgi/pom.xml new file mode 100644 index 00000000000..ef9339e6952 --- /dev/null +++ b/modules/hello-world-endpoint-dosgi/pom.xml @@ -0,0 +1,84 @@ + + + 4.0.0 + opencast-hello-world-endpoint-dosgi + bundle + Opencast :: hello-world-endpoint-dosgi + + org.opencastproject + base + 16-SNAPSHOT + ../../pom.xml + + + ${project.basedir}/../.. + false + + + + + org.opencastproject + opencast-hello-world-api + ${project.version} + + + org.opencastproject + opencast-common + ${project.version} + + + jakarta.ws.rs + jakarta.ws.rs-api + + + + org.slf4j + slf4j-api + + + org.osgi + org.osgi.service.component.annotations + + + + org.glassfish.jersey.core + jersey-server + test + + + + + + org.apache.maven.plugins + maven-dependency-plugin + true + + + + org.glassfish.jersey.core:jersey-server + + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.artifactId} + ${buildNumber} + + javax.ws.rs;version=2.0.1, + javax.ws.rs.core;version=2.0.1, + * + + + org.opencastproject.helloworld.impl;version=${project.version}, + org.opencastproject.helloworld.impl.endpoint;version=${project.version} + + + + + + + diff --git a/modules/hello-world-endpoint-dosgi/src/main/java/org/opencastproject/helloworld/impl/endpoint/HelloWorldRestEndpoint.java b/modules/hello-world-endpoint-dosgi/src/main/java/org/opencastproject/helloworld/impl/endpoint/HelloWorldRestEndpoint.java new file mode 100644 index 00000000000..b7d9784c05e --- /dev/null +++ b/modules/hello-world-endpoint-dosgi/src/main/java/org/opencastproject/helloworld/impl/endpoint/HelloWorldRestEndpoint.java @@ -0,0 +1,160 @@ +/* + * Licensed to The Apereo Foundation under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * + * The Apereo Foundation licenses this file to you under the Educational + * Community 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: + * + * http://opensource.org/licenses/ecl2.txt + * + * 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.opencastproject.helloworld.impl.endpoint; + +import org.opencastproject.helloworld.api.HelloWorldService; +import org.opencastproject.util.doc.rest.RestParameter; +import org.opencastproject.util.doc.rest.RestQuery; +import org.opencastproject.util.doc.rest.RestResponse; +import org.opencastproject.util.doc.rest.RestService; + +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +/** + * The REST endpoint for the {@link HelloWorldService} service + */ +@Component( + property = { + "service.description=Hello World REST Endpoint", + "opencast.service.type=org.opencastproject.helloworld", + "opencast.service.path=/helloworld-dosgi", + "opencast.service.jobproducer=false" + }, + immediate = true, + service = HelloWorldRestEndpoint.class +) +@Path("/") +@RestService( + name = "HelloWorldServiceEndpoint", + title = "Hello World Service Endpoint", + abstractText = "This is a tutorial service.", + notes = { + "All paths above are relative to the REST endpoint base (something like http://your.server/files)", + "If the service is down or not working it will return a status 503, this means the the " + + "underlying service is not working and is either restarting or has failed", + "A status code 500 means a general failure has occurred which is not recoverable and was " + + "not anticipated. In other words, there is a bug! You should file an error report " + + "with your server logs from the time when the error occurred: " + + "Opencast Issue Tracker" + } +) +public class HelloWorldRestEndpoint { + /** The logger */ + private static final Logger logger = LoggerFactory.getLogger(HelloWorldRestEndpoint.class); + + /** The rest docs */ + protected String docs; + + /** The service */ + protected HelloWorldService helloWorldService; + + /** + * Simple example service call + * + * @return The Hello World statement + * @throws Exception + */ + @GET + @Path("helloworld") + @Produces(MediaType.TEXT_PLAIN) + @RestQuery( + name = "helloworld", + description = "example service call", + responses = { + @RestResponse( + responseCode = HttpServletResponse.SC_OK, + description = "Hello World" + ), + @RestResponse( + responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + description = "The underlying service could not output something." + ) + }, + returnDescription = "The text that the service returns." + ) + public Response helloWorld() throws Exception { + logger.info("REST call for Hello World"); + return Response.ok().entity(helloWorldService.helloWorld()).build(); + } + + /** + * Simple example service call with parameter + * + * @param name + * the optional name of the Person to greet + * @return A Hello statement with optional name + * @throws Exception + */ + @GET + @Path("helloname") + @Produces(MediaType.TEXT_PLAIN) + @RestQuery( + name = "helloname", + description = "example service call with parameter", + restParameters = { + @RestParameter( + name = "name", + description = "name to output", + isRequired = false, + type = RestParameter.Type.TEXT + ) + }, + responses = { + @RestResponse( + responseCode = HttpServletResponse.SC_OK, + description = "Hello or Hello Name" + ), + @RestResponse( + responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + description = "The underlying service could not output something." + ) + }, + returnDescription = "The text that the service returns." + ) + public Response helloName(@FormParam("name") String name) throws Exception { + logger.info("REST call for Hello Name"); + return Response.ok().entity(helloWorldService.helloName(name)).build(); + } + + @GET + @Produces(MediaType.TEXT_HTML) + @Path("docs") + public String getDocs() { + return docs; + } + + @Reference + public void setHelloWorldService(HelloWorldService service) { + this.helloWorldService = service; + } +} diff --git a/modules/hello-world-impl/pom.xml b/modules/hello-world-impl/pom.xml index 8e6af9ddf14..bb8bb66d7d8 100644 --- a/modules/hello-world-impl/pom.xml +++ b/modules/hello-world-impl/pom.xml @@ -50,6 +50,10 @@ junit test + diff --git a/modules/hello-world-impl/src/main/java/org/opencastproject/helloworld/impl/HelloWorldServiceImpl.java b/modules/hello-world-impl/src/main/java/org/opencastproject/helloworld/impl/HelloWorldServiceImpl.java index 9aa38a457b8..a90c40f564b 100644 --- a/modules/hello-world-impl/src/main/java/org/opencastproject/helloworld/impl/HelloWorldServiceImpl.java +++ b/modules/hello-world-impl/src/main/java/org/opencastproject/helloworld/impl/HelloWorldServiceImpl.java @@ -37,7 +37,8 @@ */ @Component( property = { - "service.description=Hello World Service" + "service.description=Hello World Service", + "service.exported.interfaces=*" }, immediate = true, service = HelloWorldService.class diff --git a/pom.xml b/pom.xml index aca71ffabf2..bc7993ef828 100644 --- a/pom.xml +++ b/pom.xml @@ -44,6 +44,7 @@ 2.12.5 1.1.1 4.4.4 + 4.2.1 v18.16.0 8.0.0 8.1.0 @@ -138,6 +139,7 @@ modules/fileupload modules/hello-world-api modules/hello-world-impl + modules/hello-world-endpoint-dosgi modules/hello-world-workflowoperation modules/incident-workflowoperation modules/index-service