Need help with programmatic ATL module loading... [message #1817616] |
Tue, 26 November 2019 17:53 |
Olivier Hurez-Martin Messages: 20 Registered: May 2019 |
Junior Member |
|
|
Hello,
Please bare with me: I am relatively new to ATL...
I am trying to run multiple ATL transformations from a standalone Java application developed using Eclipse 2019-09, EMF SDK 2.19, and ATL 4.1.0 (incidentally, on Windows) and built with Maven.
The core ATL runner is inspired from:
Thank you very much to the authors of these examples!
I had to update the versions to match the application requirements, which may be part of my problem.
While attempting to load the compiled ATL module, I run into an exception:
org.eclipse.m2m.atl.emftvm.util.VMException: Error during module loading: Cannot create a resource for 'd:\Dev\LoadModule\target\test-classes\test\Class2Relational.emftvm'; a registered resource factory is needed
at org.eclipse.m2m.atl.emftvm.impl.ExecEnvImpl.loadModule(ExecEnvImpl.java:1270)
[...]
Caused by: java.lang.RuntimeException: Cannot create a resource for 'd:\Dev\LoadModule\target\test-classes\test\Class2Relational.emftvm'; a registered resource factory is needed
at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getResource(ResourceSetImpl.java:403)
at org.eclipse.m2m.atl.emftvm.util.DefaultModuleResolver.resolveModule(DefaultModuleResolver.java:67)
at org.eclipse.m2m.atl.emftvm.impl.ExecEnvImpl.loadModule(ExecEnvImpl.java:1243)
Yet, the code loads the required factories. I tried many variations - global registry or locally to the resource set passed into the module resolver. The populated maps are visible under debug. I also tried the ClassModuleResolver, as the application may eventually have to run multiple translations in parallel, but could not get that to work either (is there a working example, beyond code snippets in the doc?)
Something must be off in the environment! I spent a a lot of time trying to figure it out and reached my wits end :-/
I attached a trimmed Eclipse Maven Java project that isolates the issue in a JUnit test while preserving the relevant parts of the project structure, namely the updated dependencies (I'd welcome a documentation update with a coherent set of dependencies in their latest versions ;-)
The single, failing test case included is com.vistology.m2m.AtlRunTests.test_load_emftvm_module()
(for more independence, the transformation itself is borrowed from the ATLrunner test case)
Could someone please point out what I am doing wrong?
Thank you!
-- Olivier H.Martin.
[Updated on: Tue, 26 November 2019 18:57] Report message to a moderator
|
|
|
Re: Need help with programmatic ATL module loading... [message #1817683 is a reply to message #1817616] |
Wed, 27 November 2019 20:03 |
|
I get this error instead when running AtlRunTests:
org.eclipse.m2m.atl.emftvm.util.VMException: Error during module loading: Metamodel Relational not found
at org.eclipse.m2m.atl.emftvm.impl.ExecEnvImpl.loadModule(ExecEnvImpl.java:1270)
at org.eclipse.m2m.atl.emftvm.impl.ExecEnvImpl.loadModule(ExecEnvImpl.java:1222)
at com.vistology.m2m.AtlRunTests.test_load_emftvm_module(AtlRunTests.java:69)
Caused by: java.lang.IllegalArgumentException: Metamodel Relational not found
at org.eclipse.m2m.atl.emftvm.impl.ExecEnvImpl.findType(ExecEnvImpl.java:2068)
at org.eclipse.m2m.atl.emftvm.impl.ExecEnvImpl.findEClassifier(ExecEnvImpl.java:2159)
at org.eclipse.m2m.atl.emftvm.impl.ExecEnvImpl.registerFeature(ExecEnvImpl.java:1322)
at org.eclipse.m2m.atl.emftvm.impl.ExecEnvImpl.loadModule(ExecEnvImpl.java:1247)
... 67 more
This error is caused by the fact that you need to do env.registerMetaModel() first: the meta-classes declared in the EMFTVM module are linked against the loaded metamodel at load time, so metamodels must be present in the ExecEnv before loading any EMFTVM modules.
Cheers,
Dennis
[Updated on: Wed, 27 November 2019 20:08] Report message to a moderator
|
|
|
Re: Need help with programmatic ATL module loading... [message #1817686 is a reply to message #1817616] |
Wed, 27 November 2019 20:30 |
|
I've attached the fixed Eclipse project that works for me on my Linux machine. Chances are this still won't work for you, because EMF's URI class is not happy with Windows file paths. As you move to packaging your Maven project as a JAR file, things become gradually worse. That's why the ClassModuleResolver exists: it is robust over all stages of your development/deployment, and works cross-platform.
(In fact, I may attach a second version of the project that uses ClassModuleResolver...)
Cheers,
Dennis
|
|
|
|
|
|
Re: Need help with programmatic ATL module loading... [message #1817832 is a reply to message #1817826] |
Fri, 29 November 2019 23:58 |
|
The primary purpose of EMF's URI class was probably to provide integration with the Eclipse platform ("platform:/..." style URIs), and at the same time allow standalone usage ("file:/...", "http://..."). It does not integrate with Java's classloading/-resolving features, as found in the java.net.URL class. To bridge that gap, you have to provide an EMF's Resource content as an InputStream, which can be provided by java.net.URL.
Cheers,
Dennis
|
|
|
Re: Need help with programmatic ATL module loading... [message #1817838 is a reply to message #1817832] |
Sat, 30 November 2019 12:14 |
Olivier Hurez-Martin Messages: 20 Registered: May 2019 |
Junior Member |
|
|
About the URI... Thank you for the clarification, it makes good sense.
On the demos for DefaultModuleResolver and ClassModuleResolver:
The ClassModuleResolver method worked well on Windows, with the caveat that we lose the ability to let the user decide about the location of the transformation files.
The DefaultModuleResolver method however appears broken on Windows, as you foresaw, perhaps due to some issue with EMF URIs on Windows.
The strange part, though, is I still get the same exception about missing a resource factory registration, although all needed resource factories are registered the same way in both examples!
And the URI.createURI() method appears to work alright when registering factories and metamodels with the resource set. As a matter of fact, the part of the code that retrieves the transformation module name works well, while using the windows style URI "file:/D:/Dev/Tests/TestLoadModule/target/test-classes/test/Class2Relational.emftvm".
Here are the exception details:
org.eclipse.m2m.atl.emftvm.util.VMException: Error during module loading: Cannot create a resource for 'd:\Dev\Tests\TestLoadModule\target\test-classes\test\Class2Relational.emftvm'; a registered resource factory is needed
at org.eclipse.m2m.atl.emftvm.impl.ExecEnvImpl.loadModule(ExecEnvImpl.java:1270)
at org.eclipse.m2m.atl.emftvm.impl.ExecEnvImpl.loadModule(ExecEnvImpl.java:1222)
at com.vistology.m2m.AtlRunTests.test_load_emftvm_module(AtlRunTests.java:91)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:132)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:124)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:74)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Caused by: java.lang.RuntimeException: Cannot create a resource for 'd:\Dev\Tests\TestLoadModule\target\test-classes\test\Class2Relational.emftvm'; a registered resource factory is needed
at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getResource(ResourceSetImpl.java:403)
at org.eclipse.m2m.atl.emftvm.util.DefaultModuleResolver.resolveModule(DefaultModuleResolver.java:67)
at org.eclipse.m2m.atl.emftvm.impl.ExecEnvImpl.loadModule(ExecEnvImpl.java:1243)
... 67 more
Thanks,
-- Olivier.
[Updated on: Sat, 30 November 2019 12:39] Report message to a moderator
|
|
|
Re: Need help with programmatic ATL module loading... [message #1817905 is a reply to message #1817838] |
Mon, 02 December 2019 21:21 |
Olivier Hurez-Martin Messages: 20 Registered: May 2019 |
Junior Member |
|
|
Both methods now work on Windows...
For whomever running into the same issue on Windows, working code for both methods: DefaultModuleResolver and ClassModuleResolver, is included as distinct JUnit test cases within the attached project.
It ought to work on other platforms as well, as we stick to platform independent URIs to locate resources.
Thank you Dennis for providing the full solution with ClassModuleResolver, and the correct method using DefaultModuleResolver for Linux, which made the adaptation to Windows trivial!
Cheers,
-- Olivier.
[Updated on: Tue, 03 December 2019 20:50] Report message to a moderator
|
|
|
|
Powered by
FUDForum. Page generated in 0.02037 seconds