You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2018/09/12 07:09:36 UTC

[camel-k] branch master updated: Route loaders should derive language from 'kamel run --language' #46

This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git


The following commit(s) were added to refs/heads/master by this push:
     new d8bfcac  Route loaders should derive language from 'kamel run --language' #46
d8bfcac is described below

commit d8bfcac11d2c2fb0aaf6727a9792cdaa2e49df62
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Wed Sep 12 08:02:41 2018 +0200

    Route loaders should derive language from 'kamel run --language' #46
---
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go   |  5 ++
 pkg/build/api/types.go                             |  5 +-
 pkg/build/local/local_builder.go                   |  5 +-
 pkg/stub/action/integration/build.go               |  5 +-
 .../java/org/apache/camel/k/jvm/Application.java   | 16 ++--
 .../main/java/org/apache/camel/k/jvm/Routes.java   | 88 +++++++++++++++++++++
 .../java/org/apache/camel/k/jvm/RoutesLoader.java  | 15 ++++
 .../jvm/{RouteLoaders.java => RoutesLoaders.java}  | 91 ++++++++++------------
 .../org/apache/camel/k/jvm/ApplicationTest.java    | 16 ++++
 .../test/java/org/apache/camel/k/jvm/MyRoutes.java | 16 ++++
 ...outeLoadersTest.java => RoutesLoadersTest.java} | 44 ++++++++---
 runtime/jvm/src/test/resources/routes.mytype       |  3 +
 12 files changed, 234 insertions(+), 75 deletions(-)

diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 8b16b1e..2e4d8d2 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -277,6 +277,11 @@ func (in *SourceSpec) DeepCopyInto(out *SourceSpec) {
 		*out = new(string)
 		**out = **in
 	}
+	if in.Language != nil {
+		in, out := &in.Language, &out.Language
+		*out = new(string)
+		**out = **in
+	}
 	return
 }
 
diff --git a/pkg/build/api/types.go b/pkg/build/api/types.go
index b94a9e7..5fc1395 100644
--- a/pkg/build/api/types.go
+++ b/pkg/build/api/types.go
@@ -29,8 +29,9 @@ type BuildIdentifier struct {
 }
 
 type Code struct {
-	Name    string
-	Content string
+	Name     string
+	Content  string
+	Language string
 }
 
 // represents the result of a build
diff --git a/pkg/build/local/local_builder.go b/pkg/build/local/local_builder.go
index 38a9812..f1ed76a 100644
--- a/pkg/build/local/local_builder.go
+++ b/pkg/build/local/local_builder.go
@@ -131,8 +131,9 @@ func (b *localBuilder) execute(source build.BuildSource) (string, error) {
 			source.Code.Name: source.Code.Content,
 		},
 		Env: map[string]string{
-			"JAVA_MAIN_CLASS":    "org.apache.camel.k.jvm.Application",
-			"CAMEL_K_ROUTES_URI": "classpath:" + source.Code.Name,
+			"JAVA_MAIN_CLASS":         "org.apache.camel.k.jvm.Application",
+			"CAMEL_K_ROUTES_URI":      "classpath:" + source.Code.Name,
+			"CAMEL_K_ROUTES_LANGUAGE": source.Code.Language,
 		},
 	}
 
diff --git a/pkg/stub/action/integration/build.go b/pkg/stub/action/integration/build.go
index 25747cc..22f006a 100644
--- a/pkg/stub/action/integration/build.go
+++ b/pkg/stub/action/integration/build.go
@@ -55,8 +55,9 @@ func (b *BuildAction) Handle(integration *v1alpha1.Integration) error {
 		b.buildManager.Start(api.BuildSource{
 			Identifier: buildIdentifier,
 			Code: api.Code{
-				Name:    *integration.Spec.Source.Name,
-				Content: *integration.Spec.Source.Content,
+				Name:     *integration.Spec.Source.Name,
+				Content:  *integration.Spec.Source.Content,
+				Language: *integration.Spec.Source.Language,
 			}, // FIXME possible panic
 		})
 		logrus.Info("Build started")
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java
index dbca9f1..bec284f 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java
@@ -18,23 +18,19 @@ package org.apache.camel.k.jvm;
 
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.main.Main;
+import org.apache.camel.util.ObjectHelper;
 
 public class Application {
-    public static final String ENV_CAMEL_K_ROUTES_URI = "CAMEL_K_ROUTES_URI";
-    public static final String SCHEME_CLASSPATH = "classpath:";
-    public static final String SCHEME_FILE = "file:";
 
     public static void main(String[] args) throws Exception {
-        final String resource = System.getenv(ENV_CAMEL_K_ROUTES_URI);
+        final String resource = System.getenv(Routes.ENV_CAMEL_K_ROUTES_URI);
+        final String language = System.getenv(Routes.ENV_CAMEL_K_ROUTES_LANGUAGE);
 
-        if (resource == null || resource.trim().length() == 0) {
-            throw new IllegalStateException("No valid resource found in " + ENV_CAMEL_K_ROUTES_URI + " environment variable");
-        }
-        if (!resource.startsWith(SCHEME_CLASSPATH) && !resource.startsWith(SCHEME_FILE)) {
-            throw new IllegalStateException("No valid resource format, expected scheme:path, found " + resource);
+        if (ObjectHelper.isEmpty(resource)) {
+            throw new IllegalStateException("No valid resource found in " + Routes.ENV_CAMEL_K_ROUTES_URI + " environment variable");
         }
 
-        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RoutesLoader loader = Routes.loaderFor(resource, language);
         RouteBuilder routes = loader.load(resource);
 
         if (routes == null) {
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Routes.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Routes.java
new file mode 100644
index 0000000..b2c87d4
--- /dev/null
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Routes.java
@@ -0,0 +1,88 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache 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://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.camel.k.jvm;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import org.apache.camel.util.ObjectHelper;
+import org.apache.commons.lang3.StringUtils;
+
+public final class Routes {
+    public static final String ENV_CAMEL_K_ROUTES_URI = "CAMEL_K_ROUTES_URI";
+    public static final String ENV_CAMEL_K_ROUTES_LANGUAGE = "CAMEL_K_ROUTES_LANGUAGE";
+    public static final String SCHEME_CLASSPATH = "classpath:";
+    public static final String SCHEME_FILE = "file:";
+
+    private Routes() {
+    }
+
+    public static boolean isScripting(String resource) {
+        return resource.endsWith(".java") || resource.endsWith(".js") || resource.endsWith(".groovy");
+    }
+
+    public static RoutesLoader loaderForLanguage(String language) {
+        for (RoutesLoader loader: RoutesLoaders.values()) {
+            if (loader.getSupportedLanguages().contains(language)) {
+                return loader;
+            }
+        }
+
+        throw new IllegalArgumentException("Unable to find loader for language: " + language);
+    }
+
+    public static RoutesLoader loaderForResource(String resource) {
+        if (!resource.startsWith(SCHEME_CLASSPATH) && !resource.startsWith(SCHEME_FILE)) {
+            throw new IllegalArgumentException("No valid resource format, expected scheme:path, found " + resource);
+        }
+
+        for (RoutesLoader loader: RoutesLoaders.values()) {
+            if (loader.test(resource)) {
+                return loader;
+            }
+        }
+
+        throw new IllegalArgumentException("Unable to find loader for: " + resource);
+    }
+
+    public static RoutesLoader loaderFor(String resource, String language) {
+        if (!resource.startsWith(SCHEME_CLASSPATH) && !resource.startsWith(SCHEME_FILE)) {
+            throw new IllegalArgumentException("No valid resource format, expected scheme:path, found " + resource);
+        }
+
+        return ObjectHelper.isEmpty(language)
+            ? loaderForResource(resource)
+            : loaderForLanguage(language);
+    }
+
+    static InputStream loadResourceAsInputStream(String resource) throws IOException {
+        if (resource.startsWith(SCHEME_CLASSPATH)) {
+            String location = StringUtils.removeStart(resource, SCHEME_CLASSPATH);
+            if (!location.startsWith("/")) {
+                location = "/" + location;
+            }
+
+            return Application.class.getResourceAsStream(location);
+        } else {
+            return Files.newInputStream(
+                Paths.get(resource.substring(SCHEME_FILE.length()))
+            );
+        }
+    }
+}
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java
index 9589822..1446b55 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java
@@ -16,10 +16,25 @@
  */
 package org.apache.camel.k.jvm;
 
+import java.util.List;
 import java.util.function.Predicate;
 
 import org.apache.camel.builder.RouteBuilder;
 
 public interface RoutesLoader extends Predicate<String> {
+    /**
+     * Provides a list of the languages supported by this loader.
+     *
+     * @return the supported languages.
+     */
+    List<String> getSupportedLanguages();
+
+    /**
+     * Creates a camel {@link RouteBuilder} from the given resource.
+     *
+     * @param resource the location fo the resource to load.
+     * @return the RouteBuilder.
+     * @throws Exception
+     */
     RouteBuilder load(String resource) throws Exception;
 }
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RouteLoaders.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoaders.java
similarity index 74%
rename from runtime/jvm/src/main/java/org/apache/camel/k/jvm/RouteLoaders.java
rename to runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoaders.java
index 48a3fb6..ab1bc5c 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RouteLoaders.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoaders.java
@@ -16,12 +16,11 @@
  */
 package org.apache.camel.k.jvm;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
-import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
 import java.util.function.Function;
 import javax.script.Bindings;
 import javax.script.ScriptEngine;
@@ -40,16 +39,24 @@ import org.apache.commons.lang3.StringUtils;
 import org.codehaus.groovy.control.CompilerConfiguration;
 import org.joor.Reflect;
 
-public enum RouteLoaders implements RoutesLoader {
+import static org.apache.camel.k.jvm.Routes.SCHEME_CLASSPATH;
+
+public enum RoutesLoaders implements RoutesLoader {
     JavaClass {
         @Override
+        public List<String> getSupportedLanguages() {
+            return Arrays.asList("class");
+        }
+
+        @Override
         public boolean test(String resource) {
-            return !isScripting(resource) && hasSupportedScheme(resource);
+            //TODO: add support for compiled classes
+            return !Routes.isScripting(resource) && !resource.endsWith(".class");
         }
 
         @Override
         public RouteBuilder load(String resource) throws Exception {
-            String path = resource.substring(Application.SCHEME_CLASSPATH.length());
+            String path = resource.substring(SCHEME_CLASSPATH.length());
             Class<?> type = Class.forName(path);
 
             if (!RouteBuilder.class.isAssignableFrom(type)) {
@@ -61,13 +68,21 @@ public enum RouteLoaders implements RoutesLoader {
     },
     JavaSource {
         @Override
+        public List<String> getSupportedLanguages() {
+            return Arrays.asList("java");
+        }
+
+        @Override
         public boolean test(String resource) {
-            return isScripting(resource, "java") && hasSupportedScheme(resource);
+            String ext = StringUtils.substringAfterLast(resource, ".");
+            List<String> langs = getSupportedLanguages();
+
+            return langs.contains(ext);
         }
 
         @Override
         public RouteBuilder load(String resource) throws Exception {
-            try (InputStream is = is(resource)) {
+            try (InputStream is = Routes.loadResourceAsInputStream(resource)) {
                 String name = StringUtils.substringAfter(resource, ":");
                 name = StringUtils.removeEnd(name, ".java");
                 name = StringUtils.removeStart(name, "/");
@@ -78,8 +93,16 @@ public enum RouteLoaders implements RoutesLoader {
     },
     JavaScript {
         @Override
+        public List<String> getSupportedLanguages() {
+            return Arrays.asList("js");
+        }
+
+        @Override
         public boolean test(String resource) {
-            return isScripting(resource, "js") && hasSupportedScheme(resource);
+            String ext = StringUtils.substringAfterLast(resource, ".");
+            List<String> langs = getSupportedLanguages();
+
+            return langs.contains(ext);
         }
 
         @Override
@@ -98,7 +121,7 @@ public enum RouteLoaders implements RoutesLoader {
                     bindings.put("components", new Components(context));
                     bindings.put("from", (Function<String, RouteDefinition>) uri -> from(uri));
 
-                    try (InputStream is = is(resource)) {
+                    try (InputStream is = Routes.loadResourceAsInputStream(resource)) {
                         engine.eval(new InputStreamReader(is), bindings);
                     }
                 }
@@ -107,8 +130,16 @@ public enum RouteLoaders implements RoutesLoader {
     },
     Groovy {
         @Override
+        public List<String> getSupportedLanguages() {
+            return Arrays.asList("groovy");
+        }
+
+        @Override
         public boolean test(String resource) {
-            return isScripting(resource, "groovy") && hasSupportedScheme(resource);
+            String ext = StringUtils.substringAfterLast(resource, ".");
+            List<String> langs = getSupportedLanguages();
+
+            return langs.contains(ext);
         }
 
         @Override
@@ -122,7 +153,7 @@ public enum RouteLoaders implements RoutesLoader {
                     ClassLoader cl = Thread.currentThread().getContextClassLoader();
                     GroovyShell sh = new GroovyShell(cl, new Binding(), cc);
 
-                    try (InputStream is = is(resource)) {
+                    try (InputStream is = Routes.loadResourceAsInputStream(resource)) {
                         Reader reader = new InputStreamReader(is);
                         DelegatingScript script = (DelegatingScript) sh.parse(reader);
 
@@ -142,42 +173,6 @@ public enum RouteLoaders implements RoutesLoader {
     // TODO: move to a dedicate class
     // ********************************
 
-    public static boolean isScripting(String resource, String type) {
-        return type.startsWith(".") ? resource.endsWith(type) : resource.endsWith("." + type);
-    }
-
-    public static boolean isScripting(String resource) {
-        return resource.endsWith(".java") || resource.endsWith(".js") || resource.endsWith(".groovy");
-    }
-
-    public static boolean hasSupportedScheme(String resource) {
-        return resource.startsWith(Application.SCHEME_CLASSPATH) || resource.startsWith(Application.SCHEME_FILE);
-    }
-
-    public static RoutesLoader loaderFor(String resource) {
-        for (RoutesLoader loader: RouteLoaders.values()) {
-            if (loader.test(resource)) {
-                return loader;
-            }
-        }
-
-        throw new IllegalArgumentException("Unable to find loader for: " + resource);
-    }
-
-    private static InputStream is(String resource) throws IOException {
-        if (resource.startsWith(Application.SCHEME_CLASSPATH)) {
-            String location = StringUtils.removeStart(resource, Application.SCHEME_CLASSPATH);
-            if (!location.startsWith("/")) {
-                location = "/" + location;
-            }
-
-            return Application.class.getResourceAsStream(location);
-        } else {
-            return Files.newInputStream(
-                Paths.get(resource.substring(Application.SCHEME_FILE.length()))
-            );
-        }
-    }
 
     public static class Components {
         private CamelContext context;
diff --git a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/ApplicationTest.java b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/ApplicationTest.java
index e43d711..0b576dd 100644
--- a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/ApplicationTest.java
+++ b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/ApplicationTest.java
@@ -1,3 +1,19 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache 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://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.camel.k.jvm;
 
 import org.junit.Ignore;
diff --git a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/MyRoutes.java b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/MyRoutes.java
index c92f35a..3869f2d 100644
--- a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/MyRoutes.java
+++ b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/MyRoutes.java
@@ -1,3 +1,19 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache 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://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.camel.k.jvm;
 
 import org.apache.camel.builder.RouteBuilder;
diff --git a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RouteLoadersTest.java b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java
similarity index 70%
rename from runtime/jvm/src/test/java/org/apache/camel/k/jvm/RouteLoadersTest.java
rename to runtime/jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java
index 8701558..e083464 100644
--- a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RouteLoadersTest.java
+++ b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java
@@ -25,15 +25,15 @@ import org.junit.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-public class RouteLoadersTest {
+public class RoutesLoadersTest {
 
     @Test
     public void testLoadClass() throws Exception {
         String resource = "classpath:" + MyRoutes.class.getCanonicalName();
-        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RoutesLoader loader = Routes.loaderForResource(resource);
         RouteBuilder builder = loader.load(resource);
 
-        assertThat(loader).isSameAs(RouteLoaders.JavaClass);
+        assertThat(loader).isSameAs(RoutesLoaders.JavaClass);
         assertThat(builder).isNotNull();
 
         builder.configure();
@@ -47,10 +47,10 @@ public class RouteLoadersTest {
     @Test
     public void testLoadJava() throws Exception {
         String resource = "classpath:MyRoutes.java";
-        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RoutesLoader loader = Routes.loaderForResource(resource);
         RouteBuilder builder = loader.load(resource);
 
-        assertThat(loader).isSameAs(RouteLoaders.JavaSource);
+        assertThat(loader).isSameAs(RoutesLoaders.JavaSource);
         assertThat(builder).isNotNull();
 
         builder.configure();
@@ -64,10 +64,27 @@ public class RouteLoadersTest {
     @Test
     public void testLoadJavaScript() throws Exception {
         String resource = "classpath:routes.js";
-        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RoutesLoader loader = Routes.loaderForResource(resource);
         RouteBuilder builder = loader.load(resource);
 
-        assertThat(loader).isSameAs(RouteLoaders.JavaScript);
+        assertThat(loader).isSameAs(RoutesLoaders.JavaScript);
+        assertThat(builder).isNotNull();
+
+        builder.configure();
+
+        List<RouteDefinition> routes = builder.getRouteCollection().getRoutes();
+        assertThat(routes).hasSize(1);
+        assertThat(routes.get(0).getInputs().get(0).getEndpointUri()).isEqualTo("timer:tick");
+        assertThat(routes.get(0).getOutputs().get(0)).isInstanceOf(ToDefinition.class);
+    }
+
+    @Test
+    public void testLoadJavaScriptWithCustomExtension() throws Exception {
+        String resource = "classpath:routes.mytype";
+        RoutesLoader loader = Routes.loaderFor(resource, "js");
+        RouteBuilder builder = loader.load(resource);
+
+        assertThat(loader).isSameAs(RoutesLoaders.JavaScript);
         assertThat(builder).isNotNull();
 
         builder.configure();
@@ -81,10 +98,10 @@ public class RouteLoadersTest {
     @Test
     public void testLoadGroovy() throws Exception {
         String resource = "classpath:routes.groovy";
-        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RoutesLoader loader = Routes.loaderForResource(resource);
         RouteBuilder builder = loader.load(resource);
 
-        assertThat(loader).isSameAs(RouteLoaders.Groovy);
+        assertThat(loader).isSameAs(RoutesLoaders.Groovy);
         assertThat(builder).isNotNull();
 
         builder.configure();
@@ -97,11 +114,16 @@ public class RouteLoadersTest {
 
     @Test(expected = IllegalArgumentException.class)
     public void testResourceWithoutScheme() {
-        RouteLoaders.loaderFor("routes.js");
+        Routes.loaderForResource("routes.js");
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testResourceWithIllegalScheme() {
-        RouteLoaders.loaderFor("http:routes.js");
+        Routes.loaderForResource("http:routes.js");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testUnsupportedLanguage() {
+        Routes.loaderForLanguage("  test");
     }
 }
diff --git a/runtime/jvm/src/test/resources/routes.mytype b/runtime/jvm/src/test/resources/routes.mytype
new file mode 100644
index 0000000..0f5600d
--- /dev/null
+++ b/runtime/jvm/src/test/resources/routes.mytype
@@ -0,0 +1,3 @@
+
+from('timer:tick')
+    .to('log:info')
\ No newline at end of file