| Summary: | Integrate with JPA | ||
|---|---|---|---|
| Product: | z_Archived | Reporter: | Reinhard <r013.mantey> |
| Component: | Sapphire | Assignee: | Konstantin Komissarchik <konstantin> |
| Status: | CLOSED WONTFIX | QA Contact: | |
| Severity: | enhancement | ||
| Priority: | P3 | CC: | konstantin |
| Version: | unspecified | ||
| Target Milestone: | --- | ||
| Hardware: | All | ||
| OS: | All | ||
| Whiteboard: | |||
|
Description
Reinhard
A bit on the architecture... A Sapphire model is built in four layers: 1. Model Element Interface 2. Model Element Implementation Class 3. Resource 4. Resource Store #1 is what the developer writes. #2 is what's generated by the annotation processor when you tag the model element interface with @GenerateImpl. This part is completely agnostic of the way the data is stored. #3 is what knows how to read/write properties to a particular storage system. For instance, take a look at XmlResource class. #4 is an optional layer. It serves as the interface between various I/O systems and higher-level resource classes. For instance, take a look at FileResourceStore or UrlResourceStore. Supporting JPA as a storage system amounts to writing a new type of a resource (as opposed to altering model element implementation class). I do not know enough about JPA to know if we will also need a resource store. The XmlResource reads model annotations at runtime and configures itself accordingly, but that's certainly not the only way. You could generate a new resource class per model element type. I think there are two basic approaches: 1. Generate JPA resource classes at built time using Java APT facility (similar to how model element implementation classes are generated). We would need a new annotation to trigger this processor. Maybe @GenerateJpaResource. 2. Generate JPA resource classes at runtime directly as bytecode using a framework like ASM (http://asm.ow2.org/). I would be fine with either implementation, but note that I've been considering eliminating @GenerateImpl and its associated annotation processor in favor of runtime bytecode generation. It is a more complex approach to develop, but it would be better for adopters as it places fewer requirements on the build environment and produces skinnier production deployment units (no generated impl classes to distribute). Regarding configuring of the JPA resources, it is not practical to rename XML binding annotations. Couldn't we just re-use the actual JPA annotations at this level? ============== Sapphire is modular. This means that we will be creating new plugins and features to hold JPA support. How about org.eclipse.sapphire.jpa to hold any core API classes (like base classes for generated resources) and org.eclipse.sapphire.jpa.sdk to hold the annotation processor (assuming that's the approach). Note that this means that we wouldn't be modifying the existing processor, but rather building another processor to run adjacent to it. ============== Regarding your question on the forum about the code format... I can certainly share my code format configuration with you, but I do not require all code in the Sapphire code base to adhere to one style. I go by the following unwritten rules: 1. If you are modifying a class that you didn't write, maintain the same code style. 2. If you are writing a new class that you intend to maintain, you are free to use whatever code style you are most comfortable with. ============== Please let me know if anything above is unclear and if you need further guidance in order to get started. I am setting the target milestone to "future". This simply means that this has been triaged and we do not yet know which release this work will appear in. Once you get further along, we can pick the appropriate release. I am assigning this to myself. This is still your feature to develop, but Eclipse development process requires that a bug be assigned to a committer that is overseeing the contribution. That would be me. Thanks for the words about architecuture!
I had a look at the Resource-layer - and I have to confess, that I don't agree
with your architecture. If I got it right, you created a ResourceStore for
(at least?) every View/Editor.
Phuh! - That's what every enterprise architect tries to avoid ;)
May be it's why you modify the xml-sources before the user saves changes?
Respect to the possible approaches:
I'm only interested in the first approach.
I don't support techniques that modify bytecode at runtime, no asm, no cglib,
no aop ...
I don't like bytecode changing at all, but I do accept/use aspect weaving at
build-time. Eclipse is great to show the aspects and link the joinpoints ...
So if you plan to change sapphire model creation to happen at runtime,
I'm done with sapphire!
> Regarding configuring of the JPA resources, it is not practical to rename XML
> binding annotations. Couldn't we just re-use the actual JPA annotations at
> this level?
I did not want to rename XML annotation to avoid JPA annotations. For me, the
annotated interface is for model definition. The JPA annotated entity classes
will be generated by the annotation processor.
As I love Eclipselink, that's the only persistence implementation, I think
about.
... but as it uses almoust JPA only - the generated entity classes could be
fine for other JPA providers too.
... so the annotation processor shall create the entity classes and add them
to the persistence.xml
That's the "easy" part, which should not be hard to implement.
I have no experience with apt/annotation processing at build time, but should
be possible.
The harder part is to cut off the xml-storage processing during user editing.
User changes should go into a (buffered) presentation model, which gets
persisted on executing "save" command. But persistence operations should not
happen without "save" command.
Having such a presentation model, you won't need to implement ResourceStore
for every editor/view.
I don't know, why you created such stores.
... and don't tell me that xml is your presentation model.
For me, Xml is a format for persistence (yes I know about dom-operations).
Presentation model should be a bean - at least in java world.
Eclipse already has swt- and jface-bindings, so the connection between UI and
model is already there. Using adapters for storage, it could be possible,
store the same model to several persistence systems and there's only the need
to code one adapter for every storage system, wich is quite less than coding a
ResourceStore for every editor/view.
So before I start digging deeper: what about your plans on eliminating
@GenerateImpl - is that a definitive/unchangeable decision, or ...
kind regards
Reinhard
> I don't support techniques that modify bytecode at runtime, no asm, no cglib, > no aop ... I don't like bytecode changing at all, but I do accept/use aspect > weaving at build-time. Eclipse is great to show the aspects and link the > joinpoints ... Not modifying bytecode... Generating new classes at runtime. If you look around, that's where the industry is moving as a whole. > So before I start digging deeper: what about your plans on eliminating > @GenerateImpl - is that a definitive/unchangeable decision, or ... If there is demand for it, both runtime and built-time generation can co-exist. > I had a look at the Resource-layer - and I have to confess, that I don't agree > with your architecture. If I got it right, you created a ResourceStore for > (at least?) every View/Editor. > Phuh! - That's what every enterprise architect tries to avoid ;) > May be it's why you modify the xml-sources before the user saves changes? I do not understand what you are saying here. A resource store is abstraction layer that makes the next layer more generic. So for instance, we have FileResourceStore that can read/write a file and expose a byte array. On top of that we can put an XmlResourceStore that knows how to parse that byte array into XML DOM. On top of that sit XmlResource objects. These are created one per model element. This a flexible architecture. For instance, I can swap out FileResourceStore/XmlResourceStore for XmlEditorResourceStore to integrate with Eclipse XML editor. Nothing else changes. Or I can swap out the entire resource store and resource stack and now the same model is binding to say JPA instead of XML. > For me, the annotated interface is for model definition. The JPA annotated > entity classes will be generated by the annotation processor. Right, but couldn't JPA annotations be used at both levels? That way if you got a developer who already knows JPA, they can carry that knowledge over to specify JPA bindings in Sapphire. > As I love Eclipselink, that's the only persistence implementation, I think > about. ... but as it uses almoust JPA only - the generated entity classes > could be fine for other JPA providers too. Any JPA binding support we put into Sapphire would have to be JPA implementation agnostic. EclipseLink specific features can be used as an optimization, but cannot be required. > I have no experience with apt/annotation processing at build time, but should > be possible. Take a look at the org.eclipse.sapphire.sdk.build.processor plugin and GenerateImplProcessor class. There is a util package with classes that help with Java code generation. > The harder part is to cut off the xml-storage processing during user editing. It sounds like you are confused on the architecture. There is nothing to cut off. If you construct the model around a JPA resource, then that's how the model reads and writes properties. If you then render that model in UI, there is no XML involved anywhere in the stack. > User changes should go into a (buffered) presentation model, which gets > persisted on executing "save" command. But persistence operations should not > happen without "save" command. When a change is made in the UI, a property write happens in the model. This immediately writes through to the resource, but it is up to implementor of resource and resource store to define what happens next. You can persist immediately or you can hold changes in some sort of a buffer until save is invoked. For JPA, what I think would make sense is for the resource to set the corresponding JPA entity property and for resource store save to do a commit to the database. Note that one JPA resource store could have any number of JPA entities (resources) attached to it. > Not modifying bytecode... Generating new classes at runtime. If you look > around, that's where the industry is moving as a whole. Runtime annotation processing is ok, if it happens during development process. You need debug informations in binaries and class generation at user runtime is hard/expensive to maintain. So I say NO to the latter. >> So before I start digging deeper: what about your plans on eliminating >> @GenerateImpl - is that a definitive/unchangeable decision, or ... > If there is demand for it, both runtime and built-time generation can co-exist. OK, if you don't plan to change bytecode at (user-)runtime, let's continue :) >> I had a look at the Resource-layer - and I have to confess, that I don't agree >> with your architecture. If I got it right, you created a ResourceStore for >> (at least?) every View/Editor. >> Phuh! - That's what every enterprise architect tries to avoid ;) >> May be it's why you modify the xml-sources before the user saves changes? > I do not understand what you are saying here. A resource store is abstraction > layer that makes the next layer more generic. Sorry, I wrote ResourceStore, where I meant Resource :( The ResourceStore is ok. And Resource is not for every view, but for every file. So it might be an equivalent to JPA entity class. OK so far. >> For me, the annotated interface is for model definition. The JPA annotated >> entity classes will be generated by the annotation processor. > Right, but couldn't JPA annotations be used at both levels? That way if you got > a developer who already knows JPA, they can carry that knowledge over to > specify JPA bindings in Sapphire. If I look at the whole picture, there are annotations/model informations needed for physical storage (JPA annotation, XML annotation) and those needed for UI generation/validation. No layer needs all informations. So adding UI annotations to a JPA entity is not the right way, nor adding JPA to UI. Therefor I felt comfortable with your way of defining a model(-base) in the middle. ... but if I got it right, you don't generate anything for the UI, so using your model for physical storage only, is quite a big overhead. >> The harder part is to cut off the xml-storage processing during user editing. > It sounds like you are confused on the architecture. There is nothing to cut > off. If you construct the model around a JPA resource, then that's how the > model reads and writes properties. If you then render that model in UI, there > is no XML involved anywhere in the stack. What's about your sdef-stuff? Isn't that parsed and loaded at every application start? > Runtime annotation processing is ok, if it happens during development process. > You need debug informations in binaries and class generation at user runtime > is hard/expensive to maintain. Runtime is runtime. Implementing and debugging a runtime bytecode generation system takes a lot more work from framework developers than build time generation of source code, which is why Sapphire doesn't use this approach right now, but it has many benefits for framework users. EclipseLink, for instance, makes extensive use of bytecode generation. > And Resource is not for every view, but for every file. So it might be an > equivalent to JPA entity class. OK so far. There is a one-to-one relationship between a model element and a resource. For JPA a resource would be the entity. Something else needs to load entities/resources from database and persist changes. That would be a resource store in Sapphire terminology. I would guess that only one JPA resource store class is necessary (included in the framework rather than generated). > If I look at the whole picture, there are annotations/model informations > needed for physical storage (JPA annotation, XML annotation) and those needed > for UI generation/validation. No layer needs all informations. So adding UI > annotations to a JPA entity is not the right way, nor adding JPA to UI. > Therefor I felt comfortable with your way of defining a model(-base) in the > middle. I don't quite understand what you are trying to say here. A Sapphire model carries the semantics of the data (default values, possible values, validation, etc.) and optionally data binding specification to be used by the resource layer. For XML, we have various XML binding annotations. We need something similar for JPA. It makes sense to try to re-use existing JPA annotations. > ... but if I got it right, you don't generate anything for the UI, so using > your model for physical storage only, is quite a big overhead. UI is rendered at runtime. There is no code generation involved. The sophistication of the model layer allows for simplification of the UI layer (at least from framework user's perspective). > What's about your sdef-stuff? Isn't that parsed and loaded at every > application start? I was referring to the model being presented in the UI. UI definition (sdef) is also a Sapphire model. Currently, only XML syntax is defined, but just like with any other model, you can load the sdef model on top of a different resource (such as JPA). Don't know why you'd want to do that (even if you are writing a JPA-based enterprise app), but you could. >> Runtime annotation processing is ok, if it happens during development process. >> You need debug informations in binaries and class generation at user runtime >> is hard/expensive to maintain. > Runtime is runtime. Not for me! If runtime means, that I have a helper app, that generates the auxiliary classes on demand, its fine. So I can deploy the whole bunch at once. If I have to care about generated files at customer systems its not ok. That's really grunt work. > EclipseLink, for instance, makes extensive use of bytecode generation. Sure! And for EclipseLink its fine, as debugging stil works as expected. I generate the proxy classes for hibernate systems, as such systems don't work as expected - well, at least for me. > I would guess that only one JPA resource store class is necessary (included > in the framework rather than generated). agree. >> If I look at the whole picture, there are annotations/model informations >> needed for physical storage (JPA annotation, XML annotation) and those needed >> for UI generation/validation. No layer needs all informations. So adding UI >> annotations to a JPA entity is not the right way, nor adding JPA to UI. >> Therefor I felt comfortable with your way of defining a model(-base) in the >> middle. > I don't quite understand what you are trying to say here. When I dedicate myself to a big picture like sapphire, I first imagine each layer on a different machine. If I need things complicated, I imagine each layer at different operating system too. My typical (industrial) customers don't have reliable connection between the machines, so for planing architecture, I consider connection as weak and data-exchange between different machines as expensive. Then I look at the model information and ask myself, which layer/machine needs what kind of information. That leads to a clean architecture and a solid caching/transaction layer ... >> ... but if I got it right, you don't generate anything for the UI, so using >> your model for physical storage only, is quite a big overhead. > UI is rendered at runtime. There is no code generation involved. The > sophistication of the model layer allows for simplification of the UI layer Well, that's the point, I'm mostly interested in. > I was referring to the model being presented in the UI. UI definition (sdef) is > also a Sapphire model. Currently, only XML syntax is defined, but just like > with any other model, you can load the sdef model on top of a different > resource (such as JPA). Don't know why you'd want to do that (even if you are > writing a JPA-based enterprise app), but you could. No, its not related to JPA. But if you imagine a big company, that requires different forms for different users (managing the same entity) and all forms should be managed by the same administrator, so centralized model handling is a must. If you further imagine, that forms for RCP and Web should be managed by the same visual editor - you end up editing centralized models, which then get transformed to Eclipse Forms and ExtJS-Forms, or whatever ... A format that can be loaded from persistence into memory very quickly is the serialized format. That's why I mentioned the caching of model information using serialized format. I guess, before I start with JPA layer, I have to learn more about your sophisticated model ... kind regards Reinhard After digging deeper into sapphire model layer, I have to confess: The much I liked the idea of sapphire, the much I dislike its implementation. So I gave EMF a try and even if there's no much of sapphires sophistication, and EMF is far from being stable and reliable, almoust anything I missed at sapphire is already there. Furthermore the guys from EMF already thought about resource optimization and last not least, EMF works, like I expect things to work. So may be its more work to bring my editors to EMF, as adapting sapphire to requirements of big world, but I feel better moving ahead to EMF and learn to live with its quirks... So I say bye to sapphire. kind regards Reinhard Rather vague, but to each their own. Good luck. |