Standalone compiled OCL [message #1777950] |
Wed, 06 December 2017 11:42  |
Eclipse User |
|
|
|
Hello,
I am having trouble running compiled OCL as a standalone Java application. I am using the derived genmodel as the metamodel (which includes the OCL standard library) and when I run the program, I get:
org.eclipse.emf.ecore.resource.Resource$IOWrappedException: Package with uri 'http://www.eclipse.org/emf/2002/GenModel' not found
I have tried running this configuration using standalone interpreted OCL and it works. I have attached the complete project. The main class is test/JavaMMLauncher. Here there is a boolean flag for switching between compiled (based on OCLinEcore) and interpreted OCL (based on Pivot CompleteOCL).
I presume the issue is that the GenModel has not been added to the EPackage.Registry, but GenModel is not accessible. I was wondering if there is a workaround for this, or if the way I'm trying to use the compiled OCL is wrong?
Thanks,
Sina
|
|
|
|
Re: Standalone compiled OCL [message #1778196 is a reply to message #1777962] |
Mon, 11 December 2017 13:27   |
Eclipse User |
|
|
|
Hi Ed,
Thanks for the solution. Strangely it seems to work on one PC but not on another, both of which have Eclipse Oxygen installed with the latest OCL patch applied. I tried regenerating the genmodel and Java code, even using the same model, metamodel, generated code etc. across both computers and still on one it doesn't fix the issue on the other it does. I presume it's some quirk with EMF or at least the version installed.
On the installation where it fixes the GenModel not found issue, I get another error:
Exception in thread "main" java.lang.ExceptionInInitializerError
at javaMM.impl.JavaMMFactoryImpl.createMethodDeclaration(JavaMMFactoryImpl.java:849)
at javaMM.impl.JavaMMFactoryImpl.create(JavaMMFactoryImpl.java:227)
at org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl.createObject(XMLHelperImpl.java:885)
at org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl.createObject(XMLHelperImpl.java:922)
at org.eclipse.emf.ecore.xmi.impl.XMLHandler.createObjectFromFactory(XMLHandler.java:2222)
at org.eclipse.emf.ecore.xmi.impl.XMLHandler.createObjectFromTypeName(XMLHandler.java:2132)
at org.eclipse.emf.ecore.xmi.impl.XMLHandler.createObject(XMLHandler.java:2067)
at org.eclipse.emf.ecore.xmi.impl.XMIHandler.createObject(XMIHandler.java:151)
at org.eclipse.emf.ecore.xmi.impl.XMLHandler.handleFeature(XMLHandler.java:1876)
at org.eclipse.emf.ecore.xmi.impl.XMLHandler.processElement(XMLHandler.java:1030)
at org.eclipse.emf.ecore.xmi.impl.XMIHandler.processElement(XMIHandler.java:82)
at org.eclipse.emf.ecore.xmi.impl.XMLHandler.startElement(XMLHandler.java:1008)
at org.eclipse.emf.ecore.xmi.impl.XMLHandler.startElement(XMLHandler.java:719)
at org.eclipse.emf.ecore.xmi.impl.XMIHandler.startElement(XMIHandler.java:190)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1359)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2784)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:327)
at org.eclipse.emf.ecore.xmi.impl.XMLLoadImpl.load(XMLLoadImpl.java:175)
at org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl.doLoad(XMLResourceImpl.java:261)
at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1518)
at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1297)
at org.eclipse.epsilon.evl.engine.test.acceptance.equivalence.StandaloneOCL.preExecute(StandaloneOCL.java:186)
at org.eclipse.epsilon.profiling.ProfilableRunConfiguration.run(ProfilableRunConfiguration.java:44)
at test.JavaMMLauncher.main(JavaMMLauncher.java:28)
Caused by: org.eclipse.emf.common.util.BasicEList$BasicIndexOutOfBoundsException: index=-1, size=0
at org.eclipse.emf.common.util.BasicEList.get(BasicEList.java:346)
at javaMM.impl.JavaMMPackageImpl.getAbstractMethodDeclaration__ParametersEffectivelyFinal__DiagnosticChain_Map(JavaMMPackageImpl.java:1123)
at javaMM.impl.AbstractMethodDeclarationImpl.<clinit>(AbstractMethodDeclarationImpl.java:252)
... 32 more
Looking at the cause, the problem is in this method of JavaMMPackageImpl:
public EOperation getAbstractMethodDeclaration__ParametersEffectivelyFinal__DiagnosticChain_Map() {
return getAbstractMethodDeclaration().getEOperations().get(-1);
}
The associated OCL code with this invariant is as follows:
invariant parametersEffectivelyFinal:
(self._'body' <> null or self.parameters->isEmpty()) implies (
self._'body'.statements ->
selectByKind(ExpressionStatement) ->
collect(s | s.expression) ->
selectByKind(Assignment) ->
select(assignment |
assignment.leftHandSide.oclIsKindOf(SingleVariableAccess) and
assignment.operator = '='
) ->
isEmpty()
);
So the only way this could happen is either that the OCL code is wrong, in which case I would expect some error when running the interpretted version. Also given that an identical script was written in EVL and both the interpretted OCL and EVL version give identical results without exceptions, I doubt this could be the issue. Perhaps more likely is that the OCLinEcore version of the constraints is mis-specified, or there is a bug in the code generation.
|
|
|
|
|
|
|
|
Re: Standalone compiled OCL [message #1778359 is a reply to message #1778292] |
Wed, 13 December 2017 08:00   |
Eclipse User |
|
|
|
Hi Ed,
I was referring to the problem detailed in the third message, below the first stack trace. Sorry if this wasn't clear.
I tried regenerating again on the computer where everything works and get the same problem with "GenClass for Boolean not found". I'm not doing anything different to what I was before, and the Ecore model hasn't changed. However every time I generate the genmodel, I get HTTP 405 error, perhaps because it's trying to use the model URI as a URL, but this was happening before and the generated code didn't have any compilation errors. I haven't changed the installation of Eclipse with updates or anything of the sort though. Also I found a bug where there are NullPointerExceptions when performing the generation if the parent project has a space in its name. When I tried redoing everything in another project (without space in name), I got GenClass not found again. So finally I tried creating a new workspace and repeating the process. Again I got the same issue.
At this point I'm inclined to abandon using compiled OCL, as I seem to be getting different issues when repeating exactly the same actions on the same files under the same conditions. Once again thanks for your help, but using compiled OCL for a complex metamodel with many constraints in a standalone Java application has been more time-consuming and error-prone than I anticipated.
|
|
|
|
|
|
|
|
|
|
|
|
Re: Standalone compiled OCL [message #1779216 is a reply to message #1779207] |
Thu, 04 January 2018 01:52   |
Eclipse User |
|
|
|
Hi
Your test model has 200,000 lines defining perhaps 20,000 model elements, so based on the performance results in Fig 16 of [1] where speeds approach 1million per second you might expect an execution time of 20 ms. This is only a very rough estimate since your computer may be faster/slower, you don't have to do any output creation, you may have more validation computation per element. Instead you see 20 seconds; a 1000-fold discrepancy.
It is very unlikely that 1000-fold overhead is consumed by necessary work. Something very bad is happening. [1] shows that poor transformation scheduling can go quadratic. In [2] you can see how bad OCL tooling can be on some operations. I already identified allInstances() as bad. It can be cubic in poor implementations. Stepping your example it looked like it was quadratic. The optimizations of [2] are not yet available in Eclipse OCL.
So long as any algorithm is quadratic or worse, that is likely to dominate your performance. But you first need to get a handle on your measuring. You have not yet resolved the difference between compiled/not-compiled tests. So first ensure that both have the same number of validations of the same nodes, and that the validations produce the same results. Depending on what you actually want to measure may affect how you measure it. For instance you might choose to have an unmeasured traversal that puts all the objects in a list so that the measurements of object validation are isolated from the confounding traversal effect, which could be separately instrumented. You might choose to have a very simple failure logging to isolate the cost of BasicDiagnostic maintenance.
First debug to get predictable relevant results for your alternative execution approaches.
Then isolate the non-linear contributors, possibly by commenting out to keep only one algorithm at a time.
While debugging it may help to have a much smaller test model so that you just printf what is happening.
Regards
Ed Willink
[1] http://www.eclipse.org/mmt/qvt/docs/ICMT2017/MicromappingMoC.pdf
[2] http://www.eclipse.org/modeling/mdt/ocl/docs/publications/OCL2017Evaluation/LazyDeterminism.pdf
|
|
|
|
|
|
|
|
|
|
|
|
|