     <link rel="alternate" type="application/atom+xml" title="sebthom.de Category: Java" href="https://sebthom.de/de/category/it/development/java-coding/feed/" />
{"id":146,"date":"2010-09-08T20:56:26","date_gmt":"2010-09-08T19:56:26","guid":{"rendered":"http:\/\/sebthom.de\/?p=146&amp;langswitch_lang=de"},"modified":"2010-09-09T13:18:34","modified_gmt":"2010-09-09T12:18:34","slug":"using-emf-ecore-model-objects-with-wicket-components","status":"publish","type":"post","link":"https:\/\/sebthom.de\/de\/146-using-emf-ecore-model-objects-with-wicket-components\/","title":{"rendered":"Using EMF ECore model objects with Wicket components"},"content":{"rendered":"<p><a target=\"_blank\" href=\"http:\/\/wicket.apache.org\">Apache Wicket<\/a> uses so called <a href=\"https:\/\/cwiki.apache.org\/WICKET\/working-with-wicket-models.html\" target=\"_blank\">model objects<\/a> to bind data objects to Wicket components. The framework provides a number of model implementations to access data objects and their properties in various ways. The <a href=\"https:\/\/cwiki.apache.org\/WICKET\/working-with-wicket-models.html#WorkingwithWicketmodels-PropertyModels\" target=\"_blank\">PropertyModel<\/a> implementation for example is used to access and set the value of a Java object using reflection.<\/p>\n<h3>EPropertyModel<\/h3>\n<p>If you are working with <a target=\"_blank\" href=\"http:\/\/www.eclipse.org\/modeling\/emf\/\">EMF (Eclipse Modeling Framework)<\/a> generated model classes you can also use PropertyModels to bind structural features (properties in EMF terminology) of an EObject to a Wicket component. E.g. if your EObject has an attribute called &#8220;comment&#8221; you could instantiate a model like this<\/p>\n<pre class=\"java\" name=\"code\">IModel model = new PropertyModel(myEObject, \"comment\");\r\n<\/pre>\n<p>This approach has several disadvantages. First, the name of the attribute is declared as a String and not as a compile-time reference to the actual attribute. This means the application could break during runtime if you have renamed the attribute at one point and forgot to also change the String value. Second, this property model uses runtime reflection which is a slow alternative to compile time based access.<br \/>\nJava classes generated from EMF Models by default extend the <a href=\"http:\/\/download.eclipse.org\/modeling\/emf\/emf\/javadoc\/2.4.3\/org\/eclipse\/emf\/ecore\/EObject.html\" target=\"_blank\">EObject<\/a> class which provides a compile-time reflection API. Using the generic eGet and eSet methods any public property of the EObject can be accessed. The EMF Generator also generates a Package class for each EMF package that holds a Literals interface listing all available attributes and references of all generated EClasses of the given package. If you lets say have an EClass &#8220;Ticket&#8221; with the attribute &#8220;comment&#8221; in the package &#8220;com.acme.service&#8221; you could utilize the compile time reflection API as follows:<\/p>\n<pre class=\"java\" name=\"code\">EAttribute commentAttribute = com.acme.service.ServicePackage.Literals.TICKET__COMMENT;\r\nTicket newTicket = com.acme.service.ServiceFactory.eINSTANCE.create(Ticket.class);\r\nnewTicket.eSet(commentAttribute, \"my comment\");\r\n<\/pre>\n<p>Using the EMF compile-time reflection API I created a generic EMF ECore Feature Model implementation that leverages the compile-time references to structural features. Most of the code is actually related to working around the fact that EAttributes and EReferences are not serializable but which they should to be part safely referenced in a model that potentially is serialized by Wicket between requests.<\/p>\n<pre class=\"java\" name=\"code\">import org.apache.wicket.model.IDetachable;\r\nimport org.apache.wicket.model.IObjectClassAwareModel;\r\nimport org.eclipse.emf.ecore.EClass;\r\nimport org.eclipse.emf.ecore.EClassifier;\r\nimport org.eclipse.emf.ecore.EObject;\r\nimport org.eclipse.emf.ecore.EPackage;\r\nimport org.eclipse.emf.ecore.EStructuralFeature;\r\n\r\n\/**\r\n * A property model to bind an attribute of an EMF ECore object\r\n * \r\n * @author Sebastian Thomschke\r\n *\/\r\n@SuppressWarnings(\"unchecked\")\r\npublic class EFeatureModel&lt;T&gt; implements IObjectClassAwareModel&lt;T&gt;\r\n{\r\n\tprivate static final long serialVersionUID = 1L;\r\n\r\n\tprivate transient EStructuralFeature feat;\r\n\tprivate String featContainerClassName;\r\n\tprivate String featName;\r\n\tprivate String featPackageNsURI;\r\n\r\n\tprivate EObject target;\r\n\r\n\tpublic EFeatureModel(EObject target, EStructuralFeature efeature)\r\n\t{\r\n\t\tthis.target = target;\r\n\t\tthis.feat = efeature;\r\n\t\tthis.featName = efeature.getName();\r\n\t\tthis.featContainerClassName = efeature.getContainerClass().getName();\r\n\t\tthis.featPackageNsURI = ((EPackage) efeature.eContainer().eContainer()).getNsURI();\r\n\t}\r\n\r\n\tpublic void detach()\r\n\t{\r\n\t\tif (target instanceof IDetachable) ((IDetachable) target).detach();\r\n\t}\r\n\r\n\tpublic EStructuralFeature getFeature()\r\n\t{\r\n\t\tif (feat == null)\r\n\t\t{\r\n\t\t\tEPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(featPackageNsURI);\r\n\t\t\tfor (Object eClassifierItem : ePackage.getEClassifiers())\r\n\t\t\t{\r\n\t\t\t\tEClassifier eClassifier = (EClassifier) eClassifierItem;\r\n\t\t\t\tif (eClassifier.getInstanceClass().getName().equals(featContainerClassName))\r\n\t\t\t\t\tfeat = ((EClass) eClassifier).getEStructuralFeature(featName);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn feat;\r\n\t}\r\n\r\n\tpublic T getObject()\r\n\t{\r\n\t\treturn (T) target.eGet(getFeature());\r\n\t}\r\n\r\n\tpublic Class&lt;T&gt; getObjectClass()\r\n\t{\r\n\t\treturn getFeature().getEType().getInstanceClass();\r\n\t}\r\n\r\n\tpublic void setObject(T object)\r\n\t{\r\n\t\t\/\/ do nothing if the object is the same instance that is returned by the getter\r\n\t\t\/\/ this is esp. important for collection properties\r\n\t\tif (target.eGet(getFeature()) == object) return;\r\n\r\n\t\ttarget.eSet(getFeature(), object);\r\n\t}\r\n\r\n\t@Override\r\n\tpublic String toString()\r\n\t{\r\n\t\treturn new StringBuilder(\"Model:classname=[\").append(getClass().getName()).append(\"]\").append(\":target=[\")\r\n\t\t\t\t.append(target).append(\"]\").toString();\r\n\t}\r\n}<\/pre>\n<p>Using this new model implementation is as simple as using the PropertyModel provided by Wicket:<\/p>\n<pre class=\"java\" name=\"code\">IModel model = new EFeatureModel(myTicket, com.acme.service.ServicePackage.Literals.TICKET__COMMENT);\r\n<\/pre>\n<p>You can now fully enjoy the compile-time safeness of your EMF model.<\/p>\n<h3>Making EObjects serializable<\/h3>\n<p>Wicket usually serializes components and their associated models between HTTP requests. If you are using the provided EPropertyModel your EObject classes must implement the Serializable interface. To achieve this, simply extend the EObject interface with the Serializables interface and set &#8220;Root Extends Interface&#8221; property in your genmodel configuration to this interface.<\/p>\n<pre class=\"java\" name=\"code\">\r\n\/**\r\n * @author Sebastian Thomschke\r\n *\/\r\npublic interface SerializableEObject extends EObject, Serializable {\r\n}\r\n<\/pre>\n<p>When you now regenerate the model classes they will extend the SerializableEObject interface and Wicket will stop complaining about objects in the model being not serializable.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Apache Wicket uses so called model objects to bind data objects to Wicket components. The framework provides a number of model implementations to access data objects and their properties in various ways. The PropertyModel implementation for example is used to access and set the value of a Java object using reflection. EPropertyModel If you are&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[43],"tags":[91,89,88,30,90,87],"class_list":["post-146","post","type-post","status-publish","format-standard","hentry","category-java-coding","tag-eclipse","tag-ecore","tag-emf","tag-java","tag-reflection","tag-wicket"],"_links":{"self":[{"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/posts\/146","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/comments?post=146"}],"version-history":[{"count":0,"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/posts\/146\/revisions"}],"wp:attachment":[{"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/media?parent=146"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/categories?post=146"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sebthom.de\/de\/wp-json\/wp\/v2\/tags?post=146"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}