I build application in Java using EMF.
I use Java8 JDK.
All I need is persist instance of my model's class.
I run the code in debug mode on WildFly 10 server, remotely from Eclipse.
private String getXml(Audit audit) throws NeoflexException {
XMLResource res = new XMLResourceImpl();
res.getContents().add(audit);
StringWriter sw = new StringWriter();
try {
res.save(sw, null);
} catch (IOException e) {
throw new NeoflexException(e);
}
return sw.toString();
}
On serialization I get a NotSerializableException.
I see that generated Audit class isn't marked as Serializable.
I can not edit generated code, how ever, I also don't have option to mark this class in diagram as serializable.
As described here: https://www.eclipse.org/forums/index.php/t/261475/
I need to create an interface and derive it from serializable, but I don't have such option. See screenshot attached.
In general, EMF serializability is not bound to the ISerializable interface, but a containment hierarchy formed between the model elements. Furthermore, you should not make EMF interfaces extend the ISerializable inferface at all, as it is misleading (EMF model objects are not supposed to be serializable using the basic Java serialization).
Basically, the instances of your classes should for a containment tree: one object should be the root of the tree, and all other instances should be contained in it. Then you could save this entire containment hierarchy into a file by adding the model root into the resource.
Without knowing the concrete error message in the exception, my first tip would be to check whether the Audit element references some other model element, because if that element is referenced in a non-containment relation, than the serialization will fail.
To set a relation containment, edit your metamodel (Audit.ecore file) and set the property called containment true for the reference. However, you have to make sure that the containment subtree can be set up correctly: there is only a single model root element; all other elements can be reached by exactly one path of containment references from the model root. If an element is referenced by a cross-reference, it must also be included in the containment hierarchy in order for the EMF serialization (Resource.save) to work.
A further issue I see that you create the EMF Resource file manually, without any URI (that determines where you want to save your model) and without any resourceset (that is used to split your models into multiple files/resources with separate containment hierarchies).
In other words, you should create a ResourceSet instance, and use that to create your model Resource instances.
For more details, I suggest to check the basic and serialization specific tutorial at vogella.com.
Related
I have a metamodel in the form of an Ecore file.
I saw in some previous projects that is possible to generate an xmi file from which it is possible to edit an instance of the Ecore metamodel.
I have generated the XMI file by clicking a class in the metamodel then "Create Dynamic Instance ..." but then when I click nodes in xmi file, I miss the *new Child* command that let me to create the instance fields as in the folowing picture :
Any idea how to solve this
Well, without your metamodel and more information about exactly from which root object you created your dynamic instance, it's hard to answer properly.
Usually, if the New Child menu doesn't pop up, it's because your metaclass misses containment EReferences. The generic EMF tree editor relies on the EStructuralFeatures of each metaclass to display the various panels/menu to set information of your instances. If there is no containment references, then, no child can be created.
The title may seems confusing, but it's not easy to describe the question in few words. Let me explain the situation:
We have a web application project, and a calculation engine project. The web application collect user input and use the engine to generate some result, and represent to user. Both user input, engine output and other data will be persisted to DB using JPA.
The engine input and output consist of objects in tree structure, example like:
Class InputA {
String attrA1;
List<InputB> inputBs;
}
Class InputB {
String attrB1;
List<InputC> inputCs;
}
Class InputC {
String attrC1;
}
The engine output is in similar style.
The web application project handle the data persistence using JPA. We need to persist the engine input and output, as well as some other data that related to the input and output. Such data can be seem as extra fields to certain class. For example:
We want to persist extra field, so it looks like:
Class InputBx extends InputB{
String attrBx1;
}
Class InputCx extends InputC{
String attrCx1;
}
In Java OO world, this works, we can store a list of InputBx in InputA, and store a list of InputCx in InputBx because of the inheritance.
But we meet trouble when using JPA to persist the extended objects.
First of all, it requires the engine project to make their class become JPA entities. The engine was working fine by itself, it accept correct input and generate correct output. It doesn't smell good to force their model to become JPA entities when another project try to persist the model.
Second, the JPA doesn't accept the inherited objects when using InputA as the entry. From JPA point of view, it only know that InputA contains a list of InputB, and not possible to persist/retrieve a list of InputBx in object of InputA.
When trying to solve this, we had come up 2 ideas, but neither one satisfied us:
idea 1:
Use composition instead inheritance, so we still persist the original InputA and it's tree structure include InputB and InputC:
Class InputBx{
String attrBx1;
InputB inputB;
}
Class InputCx{
String attrCx1;
InputC inputC;
}
So the original input object tree can be smoothly retrieved, and InputBx and InputCx objects needs to be retrieved using the InputB and InputC objects in the tree as references.
The good thing is that no matter what changes made to the structure of the original input class tree (such as change attribute name, add/remove attributes in the classes), the extended class InputBx and InputCx and their attributes automatically synchronized.
The drawback is that this structure increases the calls to the database, and the model is not easy to use in the application(both back end and front end). Whenever we want related information of InputB or InputC, we need to manually code to search the corresponding object of InputBx and InputCx.
idea 2:
Manually make mirror classes to form a similar structure of the original input classes. So we created:
Class InputAx {
String attrA1;
List<InputBx> inputBs;
}
Class InputBx {
String attrB1;
List<InputCx> inputCs;
String attrBx1;
}
Class InputCx {
String attrC1;
String attrCx1;
}
We could use this as model of the web application, and the JPA entities as well. Here's what we could get:
Now the engine project can be set free, it doesn't need to bind to how the other projects persist these input/output objects. The engine project is independant now.
The JPA persistence works just fluent, no extra calls to database is required
The back end and front end UI just use this model to get both original input objects and related information with no effort. When trying use engine to perform calculation, we can use a mapping mechanism to transfer between the original objects and extended objects.
The drawback is also obvious:
There is duplication in the class structure, which is not desired from the OO point of view.
When considering it as DTO to reduce the database calls, it can be claimed as anti-pattern when using DTO in local transfer.
The structure is not automatically synchronized with the original model. So if there are any changes made to the original model, we need to manually update this model as well. If some developers forget to do this, there will be some not-easy-to-find defects.
I'm looking for the following help:
Is there any existing good/best practices or patterns to solve similar situation we meet? Or any anti-patterns that we should try to avoid? References to web articles are welcome.
If possible, can you comment on the idea 1 and idea 2, from the aspect of OO design, Persistence practices, your experience, ect.
I will be grateful for your help.
Briefly, I'm loading objects that descend from a base class using a repository defined against the base class. Although my objects are created with the correct descendant classes, any descendant classes that add navigation properties not present in the base class do not have those related objects loaded, and I have no way to explicitly request them.
Here is a simple method in a repository class that loads a given calendar event assuming you know its ID value:
public CalendarEvent GetEvent(int eventId)
{
using (var context = new CalendarEventDbContext(ConnectionString))
{
var result = (from evt in context.CalendarEvents
where eventId.Equals((int)evt.EventId)
select evt).ToList();
return result.ToList()[0];
}
}
CalendarEvent is a base class from which a large number of more specific classes descend. Entity Framework correctly determines the actual class of the calendar event specified by eventId and constructs and returns that derived class. This works perfectly.
Now, however, I have a descendant of CalendarEvent called ReportIssued. This object has a reference to another object called ReportRequest (another descendant of CalendarEvent, although I don't think that's important).
My problem is that when Entity Framework creates an instance of ReportIssued on my behalf I always want it to create and load the related instance of ReportRequested, but because I am creating the event in the context of generic calendar events, although I correctly get back a ReportIssued event, I cannot specify the .Include() to get the related object. I want to do it through this generically-expressed search because I won't necessarily know the type of eventId's event and also I have several other "Get" methods that return collections of CalendarEvent descendants.
I create my mappings using the Fluent API. I guess what I'm looking for is some way to express, in the mapping, that the related object is always wanted or, failing that, some kind of decorator that expresses the same concept.
I find it odd that when saving objects Entity Framework always walks the entire graph whereas it does not do the equivalent when loading objects.
I have an object instance, and I want to end up with a MEF catalog that contains that object instance, exported as a specific interface type. How can I do this?
TypeCatalog doesn't seem workable here, because (a) it creates a new instance instead of using an existing one, and (b) it requires the type to have an [Export] attribute. In my case, the instance comes from MEF's metadata system, so MEF creates the underlying type and I can't add attributes to it.
As far as I can tell, the usual advice is, if you've got an existing instance, you should add it to the container (e.g. via CompositionBatch), not to the catalog. But when I add this instance, I'm also adding an entire AssemblyCatalog worth of types, all in the same operation. I'll also want to be able to remove all of these types later. It makes more sense to me to bundle everything into an AggregateCatalog. That way, I can add both the assembly and the instance in one atomic operation, and I can remove them all again the same way.
For example:
// Bootstrapper code to initialize MEF:
public void Configure() {
_selectedGameCatalog = new AggregateCatalog();
var globalCatalog = new AggregateCatalog(_selectedGameCatalog);
_container = new CompositionContainer(globalCatalog);
// ... more MEF initialization ...
}
// Sometime later, I want to add more stuff to the MEF ecosystem:
public void SelectGame(Lazy<Game, IGameMetadata> entry) {
var newCatalog = new AggregateCatalog();
// Make the assembly available to import:
newCatalog.Catalogs.Add(new AssemblyCatalog(entry.Value.GetType().Assembly));
// I also want the metadata to be available to import:
IGameMetadata metadata = entry.Metadata;
newCatalog.Catalogs.Add(MakeCatalogFromInstance<IGameMetadata>(metadata));
// Replace whatever game was selected before:
_selectedGameCatalog.Catalogs.Clear();
_selectedGameCatalog.Catalogs.Add(newCatalog);
}
The part I don't know how to do is "MakeCatalogFromInstance". How can I create a catalog that contains an existing instance (registered as a specific type)?
Or, alternatively, if I'm going about this all wrong, is there a better way to plug an entire catalog and an existing instance all into MEF at the same time, with the ability to unplug them all again later and replace them with something else?
I think it's probably best to add the types to the catalog and then add the instance to the container.
Catalogs contain part definitions. Part definitions are used to create parts. (The types for this are ComposablePartDefinition and ComposablePart.) So you could theoretically write your own catalog and a part definition that always returned a part corresponding to the instance when CreatePart was called. But catalogs weren't really designed to be used this way.
For prosperity...
MEF devivides the chores of what type info is to be used (catalog) from the actual running object instances (container). To me it is a logical descicion, especially when you setup a more complex MEF environment in your application.
If you want the ability to 'change' containers on the fly, I would suggest you try to use hierarchical containers. The root catalog/container is filled with static types and any of the child containers can be filled with each specific set of meta types you need for your game.
Hope it helps,
Marc
My EF model was generated from my SQL Server database. I then generated a DomainService for RIAServices against the EF model. One of the entities is called "EntryCategories". The DomainService created this method:
public IQueryable<EntryCategories> GetEntryCategoriesSet()
{
return this.Context.EntryCategoriesSet;
}
Since my user interface display model looks quite different from the physical model, I decided to write my own DomainService for that and related entities. Yes, I know we are meant to modify the generated one but it has so much stuff in there and I wanted to focus on a small thing.
I removed the EnableClientAccess attribute from the generated DomainService and added a new class called ClientDomainService, and encapsulated in it the generated DomainService:
[EnableClientAccess()]
public class ClientDomainService : DomainService
{
// the generated domain service encapsulated in my new one.
private DataDomainService _dcds = new DataDomainService();
// reimplement one of the DataDomainService methods
public IQueryable<EntryCategories> GetEntryCategories()
{
return (from t in _dcds.GetEntryCategoriesSet() where t.EntryCategoriesVersions.EntryCategoriesVersionId == datahead.EntryCategoriesVersions.EntryCategoriesVersionId orderby t.DisplayOrder select t);
}
}
The very fist thing I tried is to reimplement the GetCateogoriesSet method but with the underlying data filtered based on another entity in my class (not shown). But when I build this, an error shows up:
Entity 'DataProject.Web.EntryCategories' has a property 'EntryCategoriesVersionsReference' with an unsupported type
If I comment out my CientDomainService, replace the EnableClientAccess attribute on the generated DomainService, and place the analagous linq filtering in the original GetEntryCategoriesSet method, the project compiles with no errors.
What is so special about the generated DomainService that my new one doesn't have? Is it that metadata.cs file?
What's special about the generated domain service is not the .metadata.cs file (you can keep it, and use it, but it doesn't solve your problem).
The problem appears somehow because RIA services (?) needs a 'domain service description provider' for the exposed Linq to EF entities. The LinqToEntitiesDomainService class has the LinqToEntitiesDomainServiceDescriptionProviderAttribute, already applied, so the generated domain services which inherit from it also inherit the provider.
When you build your own custom domain service, derived from DomainService, and expose entities through it, you need to apply this attribute yourself. Furthermore, since the provider cannot infer the object context type from the domain service base class (which it can and does if the base class is LinqToEntitiesDomainService), you need to specify the object context type in the attribute constructor, like this:
[EnableClientAccess()]
[LinqToEntitiesDomainServiceDescriptionProvider(
typeof(YourObjectContextType))]
public class ClientDomainService : DomainService
{
...
}
That should fix it.
Note that this means if you had hoped to abstract your object context away from your domain service, you'll be disappointed. I had opted for the seemingly popular repository model where all code that operates on the object context goes into a provider used by the domain service. This facilitates unit testing, but evidently doesn't remove the domain service's dependency on the object context. The context is required for RIA Services to make sense of your entites, or at least those referenced by the domain entity (such as EntryCategoriesVersions in your case).
If you want to expose a specific entity on a domain service you will have to provde at least one query method for it. This is also required when the entity is only accessed as a child of another entity.
In this case you need to add the EntryCategoriesVersions entityset to the domain service, to get the scenario working correctly.
What type is EntryCategoriesVersionsReference ? Try adding a [DataContract] annotation against the type, and appropriate [Key] and [DataMember]. It should help with marshalling.
For me, the fix for this error was to add a default constructor to the return type.
In OP's example, the property 'EntryCategories.EntryCategoriesVersionsReference' needs to be of a type with a default constructor.