Skip to content
This repository was archived by the owner on Oct 14, 2020. It is now read-only.

Commit 9df0faf

Browse files
committed
Added Gradle/Spring support to Java
- GroovyServ is no longer used. Gradle’s daemon is used instead. Unfortunately performance is about 800ms slower on avg. - Ability to customize which packages get loaded - Spring support - Ability to code blocks into multiple files (all languages) - Multi-file Java support - Improved Java exception output - Java build info is now presented within output
1 parent 9f58552 commit 9df0faf

25 files changed

+866
-243
lines changed

.dockerignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ node_modules/*
1919
docker/*
2020
.git/
2121
**/.DS_Store
22+
frameworks/java/.gradle
23+
frameworks/java/4.0
24+
frameworks/java/build
25+
frameworks/java/buildOutputCleanup

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ TestFixture.class
1111
TestFixture.java
1212
frameworks/java/CwRunListener.class
1313
frameworks/java/CwTestRunner.class
14+
frameworks/java/prewarm.status
1415
.DS_Store
1516
*~
1617
target/*
@@ -22,3 +23,7 @@ Dockerfile
2223
*.hi
2324
\#*
2425
frameworks/csharp/extra
26+
frameworks/java/.gradle
27+
frameworks/java/4.0
28+
frameworks/java/build
29+
frameworks/java/buildOutputCleanup

docker-compose.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ services:
3535
- ./examples:/runner/examples
3636
- ./frameworks:/runner/frameworks
3737
- ./test:/runner/test
38+
- ./listen.js:/runner/listen.js
3839
entrypoint: ''
3940
command: bash
4041

@@ -373,7 +374,7 @@ services:
373374
- ./examples:/runner/examples
374375
- ./frameworks:/runner/frameworks
375376
- ./test:/runner/test
376-
entrypoint: '/runner/debug.sh mocha -t 120000 test/runners/java_spec.js'
377+
entrypoint: 'mocha -t 15000 test/runners/java_spec.js'
377378

378379
clojure:
379380
image: codewars/jvm-runner

docker/java.docker

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,38 +35,62 @@ ENV PATH /usr/local/groovy/bin:${PATH}
3535
RUN mv groovyserv-1.1.0 groovyserv
3636
ENV PATH /usr/local/groovyserv/bin:${PATH}
3737

38+
# Install zip utils
39+
RUN apt-get install -y zip unzip --no-install-recommends
40+
41+
# Install Gradle
42+
ENV GRADLE_HOME /usr/local/gradle
43+
ENV GRADLE_VERSION 4.0
44+
45+
ARG GRADLE_DOWNLOAD_SHA256=56bd2dde29ba2a93903c557da1745cafd72cdd8b6b0b83c05a40ed7896b79dfe
46+
RUN set -o errexit -o nounset \
47+
&& echo "Downloading Gradle" \
48+
&& wget --no-verbose --output-document=gradle.zip "https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" \
49+
\
50+
&& echo "Checking download hash" \
51+
&& echo "${GRADLE_DOWNLOAD_SHA256} *gradle.zip" | sha256sum --check - \
52+
\
53+
&& echo "Installing Gradle" \
54+
&& unzip gradle.zip \
55+
&& rm gradle.zip \
56+
&& mv "gradle-${GRADLE_VERSION}" "${GRADLE_HOME}/" \
57+
&& ln --symbolic "${GRADLE_HOME}/bin/gradle" /usr/bin/gradle
58+
59+
RUN mkdir /usr/local/.gradle
60+
RUN chown codewarrior /usr/local/.gradle
61+
3862
# add the package json first to a tmp directory and build, copy over so that we dont rebuild every time
3963
ADD package.json /tmp/package.json
4064
RUN cd /tmp && npm install --production
4165
RUN mkdir -p /runner && cp -a /tmp/node_modules /runner
4266

43-
# ADD cli-runner and install node deps
44-
ADD . /runner
45-
46-
RUN ln -s /home/codewarrior /workspace
4767
WORKDIR /runner
68+
ADD package.json /runner/package.json
4869
RUN npm install
4970

50-
RUN /usr/local/groovyserv/bin/setup.sh
71+
# ADD cli-runner and install node deps
72+
ADD frameworks/java /runner/frameworks/java
73+
RUN chown codewarrior /runner/frameworks/java
74+
RUN ln -s /home/codewarrior /workspace
5175

52-
# create a debug entry point to make running test code easier
53-
RUN echo '#!/bin/bash\ngroovyserver -t 20 --debug --authtoken groovy || echo "server connection error"\n "$@"'>/runner/debug.sh ; chmod +x /runner/debug.sh
76+
RUN gradle --version
5477

55-
# create a specific node entry point for running the node CLI executable with groovyserve started
56-
RUN echo '#!/bin/bash\ngroovyserver -t 10 -q --authtoken groovy || echo ""\n timeout 15 node "$@"'>/runner/nodeentry.sh ; chmod +x /runner/nodeentry.sh
78+
USER codewarrior
5779

58-
RUN /runner/debug.sh groovyclient -Ct 120 -Cdebug -Cauthtoken groovy -e "println 'Hello from GroovyServ'"
80+
# pre-install the default referenced java libraries
81+
RUN cd /runner/frameworks/java && gradle --stacktrace --no-daemon compileTestJava
5982

60-
# Run the test suite to make sure this thing works
61-
USER codewarrior
83+
ADD lib /runner/lib
84+
ADD *.js /runner/
85+
ADD frameworks/java/prewarm.sh /runner/prewarm.sh
6286

6387
# Set environment variables
64-
ENV TIMEOUT 120000
6588
ENV USER codewarrior
6689
ENV HOME /home/codewarrior
67-
RUN /runner/debug.sh mocha -t ${TIMEOUT} test/runners/java_spec.js
90+
ADD test /runner/test
6891

69-
USER codewarrior
92+
# Run the test suite to make sure this thing works
93+
RUN mocha -t 20000 /runner/test/runners/java_spec.js
7094

71-
ENTRYPOINT ["/runner/nodeentry.sh"]
95+
ENTRYPOINT ["node"]
7296

documentation/environments/java.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Environment
2+
3+
Code is executed within a Dockerized Ubuntu 14.04 container.
4+
5+
## Languages
6+
7+
- Java 8 (1.8.0_91)
8+
9+
## Loaded Dependencies
10+
11+
### The following depencies are always loaded
12+
13+
- junit 4.12
14+
- lombok 1.16.18
15+
- mockito-core 2.7.19
16+
- assertj-core 3.8.0
17+
18+
### The following can be loaded through `@config reference` statements
19+
20+
- joda-time 2.2
21+
- guava 20.0
22+
- commons-lang3 3.6
23+
- commons-math3 3.6.1
24+
- jsoup 1.10.3
25+
- dom4j 2.0.1
26+
- assertj-guava 3.1.0
27+
- hibernate-core 5.2.10.Final
28+
- mongo-java-driver 3.4.2
29+
- sqlite-jdbc 3.19.3
30+
- postgresql 42.1.1
31+
- spring-boot-starter-web 1.5.4
32+
- spring-boot-starter-test 1.5.4
33+
- spring-boot-starter-data-mongodb 1.5.4
34+
- spring-boot-starter-data-redis 1.5.4
35+
- spring-boot-starter-data-jpa 1.5.4
36+
- spring-boot-starter-data-rest 1.5.4
37+
- spring-boot-starter-validation 1.5.4
38+
39+
40+
To make these packages available to the application, you must have access to the setup code block.
41+
Within the setup code you can load any of these packages using reference config statements.
42+
43+
**Setup Example:**
44+
```java
45+
// @config reference guava
46+
// @config reference commons-lang3
47+
```
48+
49+
50+
If you need to reference a package that is a dependency of one of the above packages, you will need to load those packages
51+
in order to make that dependency available.
52+
53+
### Spring Boot Packages
54+
55+
If you require support for the Spring framework, you can include `spring-boot` as the reference name.
56+
This will include both the web and test starter dependencies, as well as any additional requirements.
57+
58+
When including the Spring framework via `spring-boot`, if other services are configured, such as mongodb, then the required spring data packages will also be auto-included into the build.
59+
60+
# Build Process
61+
62+
Gradle is used as the build tool. Each time you run code, a fresh Docker container will be used. Under
63+
typical conditions the Gradle daemon should have already loaded, causing build times to typically fall within
64+
the 3 to 4 second range for trivial sized apps. However if the daemon has not finished loading then the build
65+
process may take over 10 seconds to complete.
66+
67+
# Timeout
68+
69+
The sandbox environment will timeout the code within 20 seconds.
70+
71+
> For more information, view the [docker file](https://github.com/Codewars/codewars-runner-cli/blob/master/docker/jvm.docker)

frameworks/java/build.gradle

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
plugins {
2+
id 'java'
3+
id 'groovy'
4+
}
5+
6+
repositories {
7+
jcenter()
8+
}
9+
10+
dependencies {
11+
compile 'junit:junit:4.12'
12+
compileOnly 'org.projectlombok:lombok:1.16.18'
13+
compile "joda-time:joda-time:2.2"
14+
compile 'org.mockito:mockito-core:2.7.19'
15+
compile 'com.google.guava:guava:20.0'
16+
compile 'org.apache.commons:commons-lang3:3.6'
17+
compile 'org.apache.commons:commons-math3:3.6.1'
18+
compile 'org.jsoup:jsoup:1.10.3' // jsoup HTML parser library @ https://jsoup.org/
19+
compile 'org.dom4j:dom4j:2.0.1' // Flexible XML framework
20+
compile 'org.assertj:assertj-core:3.8.0'
21+
compile 'org.assertj:assertj-guava:3.1.0'
22+
compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.0'
23+
compile 'org.hibernate:hibernate-core:5.2.10.Final'
24+
compile 'org.mongodb:mongo-java-driver:3.4.2'
25+
compile 'org.xerial:sqlite-jdbc:3.19.3'
26+
compile 'org.postgresql:postgresql:42.1.1'
27+
compile 'org.springframework:spring-orm:4.3.9.RELEASE'
28+
compile 'org.springframework.boot:spring-boot-starter-web:1.5.4.RELEASE'
29+
compile 'org.springframework.boot:spring-boot-starter-test:1.5.4.RELEASE'
30+
compile 'org.springframework.boot:spring-boot-starter-data-mongodb:1.5.4.RELEASE'
31+
compile 'org.springframework.boot:spring-boot-starter-data-redis:1.5.4.RELEASE'
32+
compile 'org.springframework.boot:spring-boot-starter-data-jpa:1.5.4.RELEASE'
33+
compile 'org.springframework.boot:spring-boot-starter-data-rest:1.5.4.RELEASE'
34+
compile 'org.springframework.boot:spring-boot-starter-validation:1.5.4.RELEASE'
35+
}
36+
37+
test {
38+
reports {
39+
html.enabled = false
40+
junitXml.enabled = false
41+
}
42+
testLogging {
43+
// TODO: Refactor so that we use Gradle to customize output, instead of custom test listener
44+
// SEE: https://stackoverflow.com/questions/3963708/gradle-how-to-display-test-results-in-the-console-in-real-time
45+
// SEE: https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.Test.html
46+
// Show standard streams so that we can parse STDOUT/ERR output.
47+
showStandardStreams = true
48+
showExceptions = true
49+
showStackTraces = true
50+
}
51+
}

frameworks/java/prewarm.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/bash
2+
3+
echo "loading" > /workspace/prewarm.status
4+
5+
# prewarm by starting the gradle daemon. Running an initial test build will also speed things up a bit
6+
cd /runner/frameworks/java && gradle --daemon --offline test
7+
8+
echo "loaded" > /workspace/prewarm.status
9+
10+
# node run -l java -c "public class Solution {}" -f "import org.junit.Test;public class TestFixture{}"
11+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import org.junit.Test;
2+
import org.junit.runners.JUnit4;
3+
//import org.hamcrest.Matchers.*;
4+
//import com.google.common.base.Optional;
5+
6+
public class Example {
7+
public Example() {
8+
}
9+
10+
public String foo(){ return "foo"; }
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import static org.junit.Assert.assertEquals;
2+
import org.junit.Test;
3+
import org.junit.runners.JUnit4;
4+
public class ExampleTest {
5+
@Test
6+
public void myTestFunction(){
7+
Example e = new Example();
8+
assertEquals("Failed Message", "foo", e.foo());
9+
}
10+
}

frameworks/java/CwRunListener.java renamed to frameworks/java/src/test/java/CwRunListener.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,26 @@ public void testFailure(final Failure failure)
1212
failed = true;
1313
final String msg = failure.getMessage();
1414
final boolean hasMessage = msg != null && msg.length() > 0;
15-
System.out.println(String.format("\n<FAILED::>%s<:LF:>", formatMessage(hasMessage ? msg : "Runtime Error Occurred")));
16-
if(!hasMessage && failure.getException() != null) {
17-
System.out.println(formatException(failure.getException()));
15+
System.out.println(String.format("\n<FAILED::>%s", formatMessage(hasMessage ? msg : "Runtime Error Occurred")));
16+
if(failure.getException() != null) {
17+
String prefix = "";
18+
if (hasMessage) {
19+
prefix = "<LOG::-Exception Details>";
20+
}
21+
22+
System.out.println(prefix + formatMessage(formatException(failure.getException())));
1823
}
1924
}
2025
public void testStarted(final Description description)
2126
{
22-
System.out.println(String.format("\n<DESCRIBE::>%s<:LF:>", formatMessage(description.getDisplayName())));
27+
System.out.println(String.format("\n<DESCRIBE::>%s", formatMessage(description.getDisplayName())));
2328
failed = false;
2429
}
2530
public void testFinished(final Description description)
2631
{
2732
if(!failed)
2833
{
29-
System.out.println("\n<PASSED::>Test Passed<:LF:>");
34+
System.out.println("\n<PASSED::>Test Passed");
3035
}
3136
System.out.println("\n<COMPLETEDIN::>");
3237
}

0 commit comments

Comments
 (0)