# 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:

- <product-location>/bin/gecko.conf - Configuration to add some JVM fine tuning and additional Java properties
- <product-location>/bin/gecko.sh - Run this script to run your application
- <product-location>/lib/launch.jar - THe monolithic jar from the default *bnd* exporter
- <product-location>/docker/Dockerfile
- <product-location>/etc/ - Folder to place configuration files
- <product-location>/logs/ - Folder where log files can end up
- <product-location>/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:

```
<dependency>
  <groupId>org.gecko.runtime</groupId>
  <artifactId>org.gecko.runtime.bnd</artifactId>
  <version>1.0.15</version>
</dependency>

<dependency>
  <groupId>org.gecko.runtime</groupId>
  <artifactId>org.gecko.templates</artifactId>
  <version>1.0.28</version>
</dependency>
```

# 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:

**<your-runtime-project>/generated/distributions/gecko.export/<your-runtime-project>.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.