# Gecko Runtime Gecko Runtime is a small toolset to create a configurable environment to run OSGi applications native or using docker. Using the corresponding **bndtools** project template, increases the ramp-up time for an application. https://gitlab.com/gecko.io/geckoRuntime The Gecko-Exporter reshapes an OSGi application into zip file that can be extracted and run. We also re-use this shape for the docker image build. *Bndtools* create as default a monolithic jar file or a corresponding deflated folder. The Gecko Runtime extends this a little bit. You end up with a folder like this: - /bin/gecko.conf - Configuration to add some JVM fine tuning and additional Java properties - /bin/gecko.sh - Run this script to run your application - /lib/launch.jar - THe monolithic jar from the default *bnd* exporter - /docker/Dockerfile - /etc/ - Folder to place configuration files - /logs/ - Folder where log files can end up - /data/ - A data location When additionally using **org.gecko.runtime.boot** all the location for *data*, *etc* and the installation dir are also published as an OSGi service in form of a *java.net.URL* ## Code and Artefacts The code for the gecko bnd-exporter can be found here: https://gitlab.com/gecko.io/geckoRuntime/-/tree/master/org.gecko.runtime.bnd The base shape of the Gecko Runtime environment comes from here: https://gitlab.com/gecko.io/geckoRuntime/-/tree/master/org.gecko.runtime.releng The bndtools project templates come from: https://gitlab.com/gecko.io/geckoRuntime/-/tree/master/org.gecko.templates The Maven Repository is currently available under: https://devel.data-in-motion.biz/nexus/repository/dim-release/ The GAV coordinates are: ``` org.gecko.runtime org.gecko.runtime.bnd 1.0.15 org.gecko.runtime org.gecko.templates 1.0.28 ``` # Gecko Runtime Exporter ## Prerequisites You need an Eclipse IDE with **bndtools** installed. You can install it using the Marketplace Client under *Help - Eclipse Marketplace*. For this turorial we used version 5 . We start creating an ordinary **bnd-workspace**. To get the project templates from the Gecko.io project we have to add the *Gecko.io* repository to the workspace: ``` -plugin.10.gecko: \ aQute.bnd.repository.maven.provider.MavenBndRepository;\ releaseUrl=https://devel.data-in-motion.biz/nexus/repository/dim-release/; \ index=${.}/gecko.maven; \ readOnly=true; \ name='Gecko.io' ``` You need to create the *gecko.maven* file for this repository and add the dependency to our template jar: ``` org.gecko.runtime:org.gecko.templates:1.0.27 ``` ![Add Gecko.io Repository](01-repository.png) ## Create Gecko Runtime Project Now, that you have access to all our project templates. Create a new *Bnd OSGi Project* and find the *Gecko OSGi Standard Templates* in the list. Just select the *Gecko Runtime Simple* template to create a setup for the Gecko Runtime. I named this project **org.gecko.runtime**. ![Select the Gecko Runtime Simple](02-runtime-project.png) Please note, that the wizard ask you for a docker group id and docker image name. This is for preparing a docker build task during the project creation. **Notice** that you have to provide the docker group name and image name in lower-case. The docker build does not support camel case docker image names. ![Docker Group id and Image Name](03-docker-setup.png) The generated project now contains an annotation *RequireRuntime* in the Java source folder. We use these annotations to define the dependencies of our application. In OSGi the modern specification take profit of these meta-annotations that provide *Requirements* in a simple and human readable way. ```java @Documented @Retention(CLASS) @Target({ TYPE, PACKAGE }) /** * Requries all the neccessary modules for the full fletched GeckoRuntime */ @RequireJaxrsWhiteboard public @interface RequireRuntime { } ``` ## Create a JaxRS Resource Now we can simply create an JaxRs resource, using the project templates. Now we want to create a *Jax-Rs Resource Component* from the *OSGi Release Templates*. I named this project **org.gecko.rest** We have now a generated JaxRs resource, that will say hello. ```java @Component(service=ExampleResource.class) @JaxrsResource public class ExampleResource { @GET @Path("example") public String sayHello() { return "Hello"; } } ``` ## Launching our Application In our **runtime** project we get a *bndrun* file that is prepared to run. In my case it is named like the project **org.gecko.runtime.bndrun**. In the *Run Requirement* section we simply add our Jax Rs project **org.gecko.rest**. Please also don't forget to select the corresponding OSGi framework. With this setup per default *org.eclipse.osgi* will be provided as reference implementation. You also should select the Java version you want to run this application with. ![Bndrun Configuration](04-launch-application.png) After hitting the resolve button. We now see all resolved dependencies for a JaxRs runtime. In our case, bnd takes the reference implementation from its repositories. ![Resolve Result](05-resolve-result.png) You now can launch everything pressing *Run OSGi*. You should end up with some log entries in the console like this: ```l Feb. 23, 2020 12:12:02 NACHM. org.apache.cxf.endpoint.ServerImpl initDestination INFORMATION: Setting the server's publish address to be / 12:12:02.544 [main] DEBUG org.apache.aries.jax.rs.whiteboard.internal.Whiteboard - Registered endpoint {org.gecko.rest.ExampleResource}={osgi.jaxrs.resource=true, service.id=64, service.bundleid=19, service.scope=bundle, component.name=org.gecko.rest.ExampleResource, component.id=0} into application .default ``` At the URL http://localhost:8080/example you should get a **Hello**! So far so good, nothing new ... ## Export the Application Before we can run the gradle build, we have to deactivate the JUnit test in the project **org.gecko.rest**. It was generated from the project templates is failes, in respect to the test-driven development paradigm. In Gradle we can also use the ``-x test` flag, to ommit tests. ```sh my@laptop:~/eclipse-workspace$ ./gradlew clean build -x test BUILD SUCCESSFUL in 3s 6 actionable tasks: 6 executed my@laptop:~/eclipse-workspace$ ``` To export the application as bundle ZIP, we simply call the corresponding Gradle task: ```bash my@laptop:~/eclipse-workspace$ ./gradlew clean build geckoExport -x test ``` When the build is finished, we will find the ZIP file artifact at: **/generated/distributions/gecko.export/.zip** If you unzip everything, there is only one thing left to do. You have to set the executable flag for the file *bin/gecko.sh*. After that you can now run the script calling *bin/gecko.sh*. As well you will get the **Hello** when calling the URL http://localhost:8080/example in your browser. ```shell my@laptop:~/tmp/org.gecko.runtime/bin$ chmod u+x gecko.sh my@laptop:~/tmp/org.gecko.runtime/bin$ ./gecko.sh ========================================================================= Gecko Bootstrap Environment JAVA: java JAVA_OPTS: -server -Xms128m -Xmx2048m -Xmn256M -XX:ParallelGCThreads=20 -XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=90 -XX:MaxTenuringThreshold=10 -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256M -Djava.net.preferIPv4Stack=true -Djava.awt.headless=true -Dconfigurator.initial=file:/home/mark/tmp/2/org.gecko.runtime/etc/config.json ========================================================================= 12:22:08.095 [main] INFO o.a.a.j.r.w.a.CxfJaxrsBundleActivator - Registered ClientBuilder 12:22:08.097 [main] INFO o.a.a.j.r.w.a.CxfJaxrsBundleActivator - Registered SseEventSourceFactory 12:22:08.193 [main] INFO org.eclipse.jetty.util.log - Logging initialized @705ms to org.eclipse.jetty.util.log.Slf4jLog 12:22:08.211 [main] INFO org.eclipse.jetty.server.Server - jetty-9.4.12.v20180830; built: 2018-08-30T13:59:14.071Z; git: 27208684755d94a92186989f695db2d7b21ebc51; jvm 11.0.6+10-post-Ubuntu-1ubuntu118.04.1 12:22:08.226 [main] INFO org.eclipse.jetty.server.session - DefaultSessionIdManager workerName=node0 12:22:08.226 [main] INFO org.eclipse.jetty.server.session - No SessionScavenger set, using defaults 12:22:08.227 [main] INFO org.eclipse.jetty.server.session - node0 Scavenging every 600000ms 12:22:08.229 [main] INFO o.e.j.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@60fa3495{/,null,AVAILABLE} 12:22:08.230 [main] INFO org.eclipse.jetty.server.Server - Started @741ms 12:22:08.230 [main] INFO org.eclipse.jetty.server.session - node0 Scavenging every 660000ms 12:22:08.284 [main] INFO o.e.jetty.server.AbstractConnector - Started ServerConnector@5fe8b721{HTTP/1.1,[http/1.1]}{0.0.0.0:8080} ``` You can stop the application hitting *ctrl-c*. ## Building Docker To create a docker image for you application use the corresponding prepared Gradle task: ```shell my@laptop:~/eclipse-workspace$ ./gradlew clean build buildDocker -x test ``` After the build you have an docker image, with the group- and image name provided before. As a default the tag *latest* is used. To test everything, issue the docker command: ```shell my@laptop:~/eclipse-workspace$ docker run -d --name test01 -p 8080:8080 gecko/testruntime:latest ``` And again under URL http://localhost:8080/example we receive our **Hello**. If you stop the container, the URL is not available anymore.