Why? Sometimes you may not have access to various resources in environments in order to encapsulate all of the dependencies of your :”script” (DISCLAIMER: You’re now basically making a full blown groovy/java project). But this could also be handy if you’ve written a groovy script and want to make it into a full blown application.
In order to do this we go to: https://start.spring.io/ and generate the project, you’ll now have something like:
extract the downloaded zip file to a directory and explore the contents:
[user@localhost somescripts]$ tree . | |
. | |
├── build.gradle | |
├── gradle | |
│ └── wrapper | |
│ ├── gradle-wrapper.jar | |
│ └── gradle-wrapper.properties | |
├── gradlew | |
├── gradlew.bat | |
├── HELP.md | |
├── settings.gradle | |
└── src | |
├── main | |
│ ├── groovy | |
│ │ └── com | |
│ │ └── codergists | |
│ │ └── somescripts | |
│ │ └── SomescriptsApplication.groovy | |
│ └── resources | |
│ └── application.properties | |
└── test | |
└── groovy | |
└── com | |
└── codergists | |
└── somescripts | |
└── SomescriptsApplicationTests.groovy | |
14 directories, 10 files |
In order to keep the application up I have decided to use a web context for spring boot, so our jar will run tomcat emedded. And I have also aligned the dependencies so the project is using the redhat blessed jars for camel/fuse/springboot. Importing a maven bom does not seem to be possible using the @Grab
groovy grapes. Hence why I am trying this in gradle.
Modify the build.gradle
like so:
plugins { | |
id 'org.springframework.boot' version '2.1.4.RELEASE' | |
id 'groovy' | |
} | |
apply plugin: 'java' | |
apply plugin: 'groovy' | |
apply plugin: 'io.spring.dependency-management' | |
apply plugin: 'org.springframework.boot' | |
group = 'com.codergists' | |
version = '0.0.1-SNAPSHOT' | |
sourceCompatibility = '1.8' | |
repositories { | |
mavenCentral() | |
maven{ | |
url "https://maven.repository.redhat.com/ga" | |
} | |
} | |
//taken from: https://maven.repository.redhat.com/ga/org/jboss/redhat-fuse/fuse-springboot-bom/ | |
dependencyManagement { | |
imports { | |
mavenBom 'org.jboss.redhat-fuse:fuse-springboot-bom:7.2.0.fuse-720020-redhat-00001' | |
} | |
} | |
dependencies { | |
implementation 'org.springframework.boot:spring-boot-starter' | |
implementation 'org.springframework.boot:spring-boot-starter-web' | |
implementation 'org.springframework.boot:spring-boot-starter-actuator' | |
implementation 'org.codehaus.groovy:groovy' | |
implementation 'javax.servlet:javax.servlet-api' | |
implementation 'org.apache.camel:camel-core' | |
implementation 'org.apache.camel:camel-servlet' | |
implementation 'org.apache.camel:camel-jackson' | |
implementation 'org.apache.camel:camel-spring-boot-starter' | |
testImplementation 'org.springframework.boot:spring-boot-starter-test' | |
} |
And also modify the src/main/groovy/SomescriptsApplication.groovy
to include a set of camel routes. An IDE like IntelliJ or Eclipse would help in order to resolve the import
statements. We have had to modify aspects of what we would be doing in a groovy script.
package com.codergists.somescripts | |
import org.springframework.boot.SpringApplication | |
import org.apache.camel.builder.RouteBuilder | |
import org.springframework.boot.autoconfigure.SpringBootApplication | |
import org.apache.camel.component.servlet.CamelHttpTransportServlet | |
import org.springframework.boot.web.servlet.ServletRegistrationBean | |
import org.springframework.context.annotation.Bean | |
import org.apache.camel.model.rest.RestBindingMode | |
import org.apache.camel.LoggingLevel | |
import org.apache.camel.Exchange | |
import org.apache.camel.Processor | |
@SpringBootApplication | |
class SomescriptsApplication extends RouteBuilder { | |
static void main(String[] args) { | |
SpringApplication.run(SomescriptsApplication, args) | |
} | |
@Bean | |
public ServletRegistrationBean camelServletRegistrationBean() { | |
ServletRegistrationBean registration = new ServletRegistrationBean(new CamelHttpTransportServlet(), "/camel/*"); | |
registration.setName("CamelServlet"); | |
return registration; | |
} | |
@Override | |
public void configure() throws Exception { | |
restConfiguration() | |
.component("servlet") | |
.bindingMode(RestBindingMode.json); | |
rest().get("/hello") | |
.to("direct:hello"); | |
from("direct:hello") | |
.log(LoggingLevel.INFO, "Hello World HTTP ENDPOINT") | |
.process(new Processor() { | |
@Override | |
void process(Exchange exchange) throws Exception { | |
def jsonMap = [hello:"world"] | |
exchange.in.body = jsonMap | |
} | |
}) | |
from("timer:hello?period=5000").log('hello world timer fired ${exchangeProperty[CamelTimerCounter]}') | |
} | |
} |
Running the application from gradle with ./gradlew bootRun
will confirm the camel context is using the specified fuse version 2.21.0.fuse-720050-redhat-00001
[user@localhost somescripts]$ ./gradlew bootRun | |
> Task :bootRun | |
. ____ _ __ _ _ | |
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ | |
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ | |
\\/ ___)| |_)| | | | | || (_| | ) ) ) ) | |
' |____| .__|_| |_|_| |_\__, | / / / / | |
=========|_|==============|___/=/_/_/_/ | |
:: Spring Boot :: (v1.5.16.RELEASE) | |
... | |
2019-05-07 13:44:01.968 INFO 7497 --- [ main] o.a.camel.spring.SpringCamelContext : Apache Camel 2.21.0.fuse-720050-redhat-00001 (CamelContext: camel-1) started in 0.300 seconds | |
2019-05-07 13:44:01.985 INFO 7497 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) | |
2019-05-07 13:44:01.989 INFO 7497 --- [ main] c.c.somescripts.SomescriptsApplication : Started SomescriptsApplication in 4.702 seconds (JVM running for 5.19) | |
2019-05-07 13:44:02.981 INFO 7497 --- [- timer://hello] route3 : hello world timer fired 1 | |
2019-05-07 13:44:07.968 INFO 7497 --- [- timer://hello] route3 : hello world timer fired 2 | |
2019-05-07 13:44:12.968 INFO 7497 --- [- timer://hello] route3 : hello world timer fired 3 | |
<==========---> 80% EXECUTING [22s] | |
> :bootRun |
And we can confirm that the project is using the Red Hat Fuse dependencies by running ./gradlew dependencies
[user@localhost somescripts]$ ./gradlew dependencies | |
> Task :dependencies | |
------------------------------------------------------------ | |
Root project | |
------------------------------------------------------------ | |
<<< REDACTED >>> | |
compileClasspath - Compile classpath for source set 'main'. | |
+--- org.springframework.boot:spring-boot-starter -> 1.5.16.RELEASE | |
| +--- org.springframework.boot:spring-boot:1.5.16.RELEASE | |
<<< REDACTED >>> | |
+--- org.apache.camel:camel-core -> 2.21.0.fuse-720050-redhat-00001 | |
| +--- org.slf4j:slf4j-api:1.7.22.redhat-2 | |
| +--- com.sun.xml.bind:jaxb-core:2.2.11.redhat-4 | |
| \--- com.sun.xml.bind:jaxb-impl:2.2.11.redhat-4 | |
+--- org.apache.camel:camel-servlet -> 2.21.0.fuse-720050-redhat-00001 | |
| +--- org.apache.camel:camel-core:2.21.0.fuse-720050-redhat-00001 (*) | |
| \--- org.apache.camel:camel-http-common:2.21.0.fuse-720050-redhat-00001 | |
| \--- org.apache.camel:camel-core:2.21.0.fuse-720050-redhat-00001 (*) | |
+--- org.apache.camel:camel-jackson -> 2.21.0.fuse-720050-redhat-00001 | |
| +--- org.apache.camel:camel-core:2.21.0.fuse-720050-redhat-00001 (*) | |
| +--- com.fasterxml.jackson.core:jackson-databind:2.8.11.1 -> 2.8.11.2 (*) | |
| \--- com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.8.11 | |
| +--- com.fasterxml.jackson.core:jackson-core:2.8.11 | |
| +--- com.fasterxml.jackson.core:jackson-annotations:2.8.0 | |
| \--- com.fasterxml.jackson.core:jackson-databind:2.8.11 -> 2.8.11.2 (*) | |
\--- org.apache.camel:camel-spring-boot-starter -> 2.21.0.fuse-720050-redhat-00001 | |
+--- org.springframework.boot:spring-boot-starter:1.5.10.RELEASE -> 1.5.16.RELEASE (*) | |
+--- org.apache.camel:camel-spring-boot:2.21.0.fuse-720050-redhat-00001 | |
| \--- org.apache.camel:camel-spring:2.21.0.fuse-720050-redhat-00001 | |
| +--- org.apache.camel:camel-core:2.21.0.fuse-720050-redhat-00001 (*) | |
| +--- org.springframework:spring-core:4.3.17.RELEASE -> 4.3.19.RELEASE | |
| +--- org.springframework:spring-aop:4.3.17.RELEASE -> 4.3.19.RELEASE (*) | |
<<< REDACTED >>> |
In order to create a fat spring-boot jar we run ./gradlew bootjar
[user@localhost somescripts]$ ./gradlew bootjar | |
BUILD SUCCESSFUL in 2s | |
3 actionable tasks: 3 executed |
We can now see that a build
has been generated with a somescripts-0.0.1-SNAPSHOT.jar
[user@localhost somescripts]$ tree | |
. | |
├── build | |
│ ├── classes | |
│ │ └── groovy | |
│ │ └── main | |
│ │ └── com | |
│ │ └── codergists | |
│ │ └── somescripts | |
│ │ ├── SomescriptsApplication$1.class | |
│ │ └── SomescriptsApplication.class | |
│ ├── generated | |
│ │ └── sources | |
│ │ └── annotationProcessor | |
│ │ └── groovy | |
│ │ └── main | |
│ ├── libs | |
│ │ └── somescripts-0.0.1-SNAPSHOT.jar | |
│ ├── resources | |
│ │ └── main | |
│ │ └── application.properties | |
│ └── tmp | |
│ ├── bootJar | |
│ │ └── MANIFEST.MF | |
│ └── compileGroovy | |
│ └── groovy-java-stubs |
[user@localhost somescripts]$ ls -lah ./build/libs/somescripts-0.0.1-SNAPSHOT.jar | |
-rw-rw-r--. 1 user user 26M May 7 13:56 ./build/libs/somescripts-0.0.1-SNAPSHOT.jar |
This jar is now portable and should run anywhere with java 8 by running java -jar ${jarfile}
as below:
[user@localhost somescripts]$ java -jar ./build/libs/somescripts-0.0.1-SNAPSHOT.jar | |
. ____ _ __ _ _ | |
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ | |
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ | |
\\/ ___)| |_)| | | | | || (_| | ) ) ) ) | |
' |____| .__|_| |_|_| |_\__, | / / / / | |
=========|_|==============|___/=/_/_/_/ | |
:: Spring Boot :: (v1.5.16.RELEASE) | |
2019-05-07 14:07:55.860 INFO 8842 --- [ main] c.c.somescripts.SomescriptsApplication : Starting SomescriptsApplication | |
<< REDACTED >> |
You should also be able to confirm that the REST service is available with curl
[user@localhost somescripts]$ curl localhost:8080/camel/hello | |
{"hello":"world"} |