-
Notifications
You must be signed in to change notification settings - Fork 191
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ref #4407: js-dsl - Improve the interoperability with Java code
- Loading branch information
Showing
25 changed files
with
1,135 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
Since the function `Java.extend` https://www.graalvm.org/latest/reference-manual/js/JavaInteroperability/#extending-java-classes[is only available in JVM mode], by default, there is no way to implement a functional interface like a `Camel Processor` in JavaScript that is supported by the native compilation. | ||
|
||
As workaround, an implementation of the main functional interfaces (`org.apache.camel.Processor`, `java.util.function.Consumer`, `java.util.function.Supplier`, `java.util.function.Function`, `java.util.function.Predicate`, `java.util.function.BiConsumer`, `java.util.function.BiFunction` and `java.util.function.BiPredicate`) is available in the package `org.apache.camel.quarkus.dsl.js.runtime` whose simple name is prefixed by `JavaScriptDsl`. For each implementation, the body of the method to implement must be provided to the constructor. When the method to implement has arguments, the name of the arguments can also be provided to the constructor if the default names are not good enough. | ||
|
||
So for example, to implement a `Camel Processor` instead of using the function `Java.extend` which is only available in JVM mode as next: | ||
|
||
[source,javascript] | ||
---- | ||
const Processor = Java.type("org.apache.camel.Processor"); // <1> | ||
const p = Java.extend(Processor); // <2> | ||
const a = new p(e => { e.getMessage().setBody('Some Content') }); // <3> | ||
from('direct:a') | ||
.process(a); // <4> | ||
---- | ||
<1> Retrieve the class `org.apache.camel.Processor` | ||
<2> Create a new class that implements the functional interface `org.apache.camel.Processor` | ||
<3> Instantiate the new class with a function as argument representing the implementation of the method to implement | ||
<4> Provide the processor to the route definition. | ||
|
||
To have a code compatible with the both mods, it is possible to instantiate directly the implementation of corresponding functional interface which is in this case the class `org.apache.camel.quarkus.dsl.js.runtime.JavaScriptDslProcessor` as next: | ||
|
||
[source,javascript] | ||
---- | ||
const Processor = Java.type("org.apache.camel.quarkus.dsl.js.runtime.JavaScriptDslProcessor"); // <1> | ||
const p = new Processor("e", `e.getMessage().setBody('Some Content')`); // <2> | ||
from('direct:a') | ||
.process(p); // <3> | ||
---- | ||
<1> Retrieve the class `org.apache.camel.quarkus.dsl.js.runtime.JavaScriptDslProcessor` | ||
<2> Instantiate the dedicated class with the name of the argument `e` as first parameter and the body of the function as second parameter representing the implementation of the method to implement | ||
<3> Provide the processor to the route definition. |
81 changes: 81 additions & 0 deletions
81
...untime/src/main/java/org/apache/camel/quarkus/dsl/js/runtime/JavaScriptDslBiConsumer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* | ||
* 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.quarkus.dsl.js.runtime; | ||
|
||
import java.util.function.BiConsumer; | ||
|
||
import org.graalvm.polyglot.Context; | ||
import org.graalvm.polyglot.Value; | ||
|
||
import static org.apache.camel.dsl.js.JavaScriptRoutesBuilderLoader.LANGUAGE_ID; | ||
|
||
/** | ||
* {@code JavaScriptDslBiConsumer} is meant to be used as type of {@link BiConsumer} from a JavaScript file to remain | ||
* compatible | ||
* with the native mode that doesn't support the function {@code Java.extend}. | ||
* | ||
* @param <T> the type of the first argument to the operation | ||
* @param <U> the type of the second argument to the operation | ||
*/ | ||
public final class JavaScriptDslBiConsumer<T, U> implements BiConsumer<T, U> { | ||
|
||
/** | ||
* The name of the first argument. | ||
*/ | ||
private final String firstArgumentName; | ||
/** | ||
* The name of the second argument. | ||
*/ | ||
private final String secondArgumentName; | ||
/** | ||
* The source of the consumer. | ||
*/ | ||
private final CharSequence source; | ||
|
||
/** | ||
* Construct a {@code JavaScriptDslConsumer} with the given source, {@code t} as first argument name and {@code u} as | ||
* second argument. | ||
* | ||
* @param source the source of the consumer. | ||
*/ | ||
public JavaScriptDslBiConsumer(CharSequence source) { | ||
this("t", "u", source); | ||
} | ||
|
||
/** | ||
* Construct a {@code JavaScriptDslConsumer} with the given source and argument names. | ||
* | ||
* @param firstArgumentName the name of the first argument. | ||
* @param secondArgumentName the name of the second argument. | ||
* @param source the source of the consumer. | ||
*/ | ||
public JavaScriptDslBiConsumer(String firstArgumentName, String secondArgumentName, CharSequence source) { | ||
this.firstArgumentName = firstArgumentName; | ||
this.secondArgumentName = secondArgumentName; | ||
this.source = source; | ||
} | ||
|
||
@Override | ||
public void accept(T t, U u) { | ||
try (final Context context = JavaScriptDslHelper.createBuilder().build()) { | ||
final Value bindings = context.getBindings(LANGUAGE_ID); | ||
bindings.putMember(firstArgumentName, t); | ||
bindings.putMember(secondArgumentName, u); | ||
context.eval(LANGUAGE_ID, source); | ||
} | ||
} | ||
} |
84 changes: 84 additions & 0 deletions
84
...untime/src/main/java/org/apache/camel/quarkus/dsl/js/runtime/JavaScriptDslBiFunction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* 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.quarkus.dsl.js.runtime; | ||
|
||
import java.util.function.BiFunction; | ||
|
||
import org.graalvm.polyglot.Context; | ||
import org.graalvm.polyglot.Value; | ||
|
||
import static org.apache.camel.dsl.js.JavaScriptRoutesBuilderLoader.LANGUAGE_ID; | ||
|
||
/** | ||
* {@code JavaScriptDslBiFunction} is meant to be used as type of {@link BiFunction} from a JavaScript file to remain | ||
* compatible | ||
* with the native mode that doesn't support the function {@code Java.extend}. | ||
* | ||
* @param <T> the type of the first argument to the function | ||
* @param <U> the type of the second argument to the function | ||
* @param <R> the type of the result of the function | ||
*/ | ||
public final class JavaScriptDslBiFunction<T, U, R> implements BiFunction<T, U, R> { | ||
|
||
/** | ||
* The name of the first argument. | ||
*/ | ||
private final String firstArgumentName; | ||
/** | ||
* The name of the second argument. | ||
*/ | ||
private final String secondArgumentName; | ||
/** | ||
* The source of the function. | ||
*/ | ||
private final CharSequence source; | ||
|
||
/** | ||
* Construct a {@code JavaScriptDslBiFunction} with the given source, {@code t} as first argument name and {@code u} as | ||
* second argument. | ||
* | ||
* @param source the source of the function. | ||
*/ | ||
public JavaScriptDslBiFunction(CharSequence source) { | ||
this("t", "u", source); | ||
} | ||
|
||
/** | ||
* Construct a {@code JavaScriptDslBiFunction} with the given source and argument names. | ||
* | ||
* @param firstArgumentName the name of the first argument. | ||
* @param secondArgumentName the name of the second argument. | ||
* @param source the source of the function. | ||
*/ | ||
public JavaScriptDslBiFunction(String firstArgumentName, String secondArgumentName, CharSequence source) { | ||
this.firstArgumentName = firstArgumentName; | ||
this.secondArgumentName = secondArgumentName; | ||
this.source = source; | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
@Override | ||
public R apply(T t, U u) { | ||
try (final Context context = JavaScriptDslHelper.createBuilder().build()) { | ||
final Value bindings = context.getBindings(LANGUAGE_ID); | ||
bindings.putMember(firstArgumentName, t); | ||
bindings.putMember(secondArgumentName, u); | ||
Value value = context.eval(LANGUAGE_ID, source); | ||
return value == null ? null : (R) value.as(Object.class); | ||
} | ||
} | ||
} |
Oops, something went wrong.