Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] Best practices for modularity?

ah, I see.  This is an interesting strategy.  It gives me a lot of food for
thought, and I'll definitely keep it in mind.  

Thanks,
Polly


Blaise Doughan wrote:
> 
> Hi Polly,
> 
> I'm going to try and develop this a little more but here are some 
> current thoughts:
> 
> We use MOXy to map our XML mapping data to our programmatic metadata.  
> This means that you could use MOXy to unmarshal your XML metadata files 
> into the programmatic metadata:
> 
>     import java.io.File;
>     import 
> org.eclipse.persistence.internal.sessions.factories.EclipseLinkObjectPersistenceRuntimeXMLProject;
>     import org.eclipse.persistence.oxm.*;
>     import org.eclipse.persistence.sessions.Project;
>     ...
>     EclipseLinkObjectPersistenceRuntimeXMLProject project = new 
> EclipseLinkObjectPersistenceRuntimeXMLProject();
>     XMLContext xmlContext = new XMLContext(project);
> 
>     XMLUnmarshaller unmarshaller = xmlContext.createUnmarshaller();
>     Project baseProject = (Project) unmarshaller.unmarshal(new 
> File("your_base_metadata.xml"));
>     Project extensionProject = (Project) unmarshaller.unmarshal(new 
> File("your_extension_metadata.xml"));
> 
> Then you could pull data from extensionProject into the baseProject, 
> useful methods here are the following:
> 
>     XMLDescriptor customerDescriptor = (XMLDescriptor) 
> project.getClassDescriptor(Customer.class);
>     XMLDirectMapping firstNameMapping = (XMLDirectMapping) 
> customerDescriptor.getMappingForAttributeName("firstName");
> 
> Finally you would create an XMLContext on your combined project, if you 
> moved everything into your base project, then this would be done as
> follows:
> 
>     XMLContext xmlContext2 = new XMLContext(baseProject);
> 
> ---
> 
> Other Items:
> 
>     * You are correct you can not use multiple Any mappings at the same
>       level.
>     * To get the xsi prefix to appear in the out document, in the UI be
>       sure that in the schemas panel it is selected as a declaration to
>       be included, or programmatically add it to the NamespaceResolver
>       held onto by the descriptor.
> 
> 
> -Blaise
> 
> amphoras wrote:
>> Hi Blaise,
>>
>> Thanks for your detailed and helpful response.  I just have a few more
>> questions.
>>
>>   
>>>> 1.  What does it mean to have a "primary" project versus "additional"
>>>> projects in the session?  The documentation talks about how to
>>>> configure
>>>> these but doesn't really go into the ramifications.  Does the order of
>>>>       
>>> the
>>>     
>>>> projects matter?
>>>>       
>>
>>   
>>> I never really thought of it as primary vs additional projects.  Each
>>> project is equal, the order is only 
>>> significant if you have multiple objects mapped to the same default root
>>> element.  As a default root 
>>> element must correspond to only one descriptor.
>>>     
>>
>> What I was trying to do was create an incomplete/abstract mapping for a
>> class in my "common" project.xml file.  Then I created another mapping
>> for
>> the same class in my "app" project.xml file that fills in the missing
>> pieces
>> and overrides certain settings from the "common" mapping.  My session.xml
>> file loads both project files.  
>>
>> I found that since both mappings are for the same class, whichever one
>> that
>> I set as the "primary" in the session was wiped out by the second one. 
>> Actually, all settings were replaced except for one.  The "common" and
>> "app"
>> versions of the class mappings have different "default root element"
>> settings, and I found that both were available for unmarshalling.  So the
>> result was cumulative.  It sounds like you expect that the default root
>> element should have been replaced by the second class mapping?
>>
>> ---
>>
>>   
>>>> 2.  Is is possible for an application's mappings to override the ones
>>>>       
>>> from
>>>     
>>>> the common project?
>>>>       
>>
>>   
>>> I'll describe a strategy we use to unmarshal our own metadata.  We use 
>>> the Java version of the metadata  and create a subclass of the project 
>>> for each version that we distribute.  Each descriptor is built in its 
>>> own method, and when new features are added the corresponding mapping 
>>> project overrides the corresponding buildDescriptor method.
>>> ...
>>>     
>>
>> yes, that is the exact behavior that I'm looking for!  Is it possible to
>> do
>> this using the deployment project.xml files?  I am trying to do as much
>> as I
>> can using the xml files.  I am ok with creating event listeners like the
>> amendment method, but I am trying to minimize use of Java for ease of
>> changing the mappings.
>>
>> ---
>>
>>   
>>>> 3.  Is is possible for the common project to define mappings that are
>>>> "abstract" or based on interfaces?  I see that there is an
>>>> XMLChoiceMapping, but I am not sure how to use that because I won't
>>>> know
>>>> ahead of time what application-specific class I need to use.  I would
>>>>       
>>> like
>>>     
>>>> to have a common POJO that contains composite objects that are defined
>>>>       
>>> in
>>>     
>>>> the application-specific project.  Is that possible?
>>>>       
>>
>>   
>>> I have seen users make use of our Any mappings for this.  Their scenario 
>>> is usually the following, they have one OXM project that corresponds to 
>>> the message envelope, and many OXM projects that correspond to possible 
>>> payloads.  To implement this they use an XMLAnyObjectMapping to map the 
>>> message body property on their message object, and then in the payload 
>>> projects they ensure that all of objects that form the root of the body 
>>> have default root elements set.  You will need to ensure that the 
>>> XMLContext is created with both the message and payload projects.
>>>     
>>
>> yes, exactly.  I have an element like this:
>>
>> <Foo>
>>     <Action></Action>
>>     <Data></Data>
>>     <Data></Data>
>>     ...
>> </Foo>
>>
>> "Action" is a class hierarchy of different kinds of actions, and "Data"
>> is a
>> collection of any type of element.  So I configured "Action" with an
>> XMLChoiceMapping and "Data" as XMLAnyCollectionMapping, and that works! 
>> I
>> did try to set "Action" to XMLAnyObjectMapping, but EclipseLink got
>> confused.  So I guess you can't use two "any" mappings next to one
>> another,
>> which makes sense.  The XMLChoiceMapping works fine for the "Action".
>>
>> The only problem is when I try to go roundtrip more than once.  I can
>> unmarshall the document and marshall it back out, but the Action element
>> is
>> output with the attribute 'xsi:type="ns1:ProcessType"'.  I don't think
>> this
>> attribute is allowed by the schema, and when I unmarshall the document
>> again, I get:
>>
>> [Fatal Error] :178:72: The prefix "xsi" for attribute "xsi:type"
>> associated
>> with an element type "ns1:Process" is not bound.
>>
>> I noticed that the "xsi" namespace is not defined in the output file even
>> though it was in the original one.  So my questions are:
>>
>> a.  Can I suppress the xsi:type attribute from being generated?
>> b.  Failing that, I need to get this attribute added to the schema,
>> correct?  
>> c.  How do I get the "xsi" namespace to be generated for the output?
>>
>> ---
>>
>>   
>>>> 4.  Is is possible to map different root elements to the same POJO?  Or
>>>> can I use a regular expression when matching the root element name? 
>>>> Our
>>>> schema is defined such that we have root elements with different names
>>>> that have very similar content, so I'd like to be able to map them to
>>>>       
>>> the
>>>     
>>>> same POJO.  From what I've seen from the code, it looks like I will not
>>>>       
>>> be
>>>     
>>>> able to do this directly.  So I think my alternative is to come up with
>>>>       
>>> a
>>>     
>>>> transformation to apply before unmarshalling and after marshalling to
>>>> change the root element name.  Or do you have other suggestions?
>>>>       
>>
>>   
>>> You can map multiple root elements to the same POJO.  Currently this can 
>>> not be done in the UI, but you can create an "After Load" method and 
>>> modify the descriptor by hand.  You can call 
>>> "setDefaultRootElement(String)" multiple times on the descriptor.  All 
>>> of these names will be used to recognize the object during 
>>> unmarshalling, but the last defaultRootElement set will be used for 
>>> marshalling.  
>>>     
>>
>> Hmm, my scenario is that the class mapping is in the "common" project,
>> and I
>> won't know what the possible default root elements are ahead of time. 
>> Only
>> the "app" project will know that, and it needs to define multiple root
>> elements (around 5).  So I cannot call setDefaultRootElement() from the
>> amendment method while the "common" project is loading.  This is similar
>> to
>> the "data" element in question 3 that was solved by the "any" mapping.  I
>> need to go roundtrip using these many root elements, so marshalling using
>> the last defined root element also won't work.  
>>
>>   
>>> If you want to use a different root element, you can wrap 
>>> your object in an instance of org.eclipse.persistence.oxm.XMLRoot of 
>>> javax.xml.bind.JAXBElement (if your are using JAXB).
>>>     
>>
>> can you clarify this?  I've never actually worked with JAXB directly.  So
>> far I've been very happy to let EclipseLink hide JAXB under the covers. 
>> ;)
>>
>> If I can marshall to those different root elements using a callback
>> method,
>> that would be fine.  I can figure out what root element to use based on
>> data
>> inside the object.
>>
>> Or... would the "preserve document" setting help in this case?
>>
>> ---
>>
>>   
>>>> 5.  Can you share any other best practices for implementing a modular
>>>> design with these mappings?
>>>>       
>>
>>   
>>> I mentioned a couple of our most common strategies above.  Can you share 
>>> more details about the type of modularity you would like to see?
>>>     
>>
>> sure, I'll summarize from my response above:
>> * ability to allow the project.xml files to inherit and override mappings
>> like you are doing with Java.
>> * ability to defer defining root elements to another project.xml file.  
>> * ability to marshall using different root elements using a callback
>> method
>> or some way to "remember" what was unmarshalled.
>>
>> Thanks for your help!  This is much easier than debugging random
>> EclipseLink
>> source code in hope of finding a hint.  :)
>>
>> --Polly
>>   
> 
> _______________________________________________
> eclipselink-users mailing list
> eclipselink-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
> 
> 

-- 
View this message in context: http://www.nabble.com/Best-practices-for-modularity--tp18654654p18819875.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.



Back to the top