Re: [Simple-support] Using constructors with arguments
Brought to you by:
niallg
|
From: Niall G. <gal...@ya...> - 2009-01-26 19:40:54
|
Hi, Take a look at this. I will add this form of instantiation without a no-arg constructor in the next release. http://simple.svn.sourceforge.net/viewvc/simple/trunk/download/stream/src/test/java/org/simpleframework/xml/core/ObjectStreamClassTest.java?revision=1158&view=markup Let me know if this is suitable. Niall --- On Mon, 1/26/09, Niall Gallagher <gal...@ya...> wrote: > From: Niall Gallagher <gal...@ya...> > Subject: Re: [Simple-support] Using constructors with arguments > To: sim...@li..., "Kevin Day" <for...@tr...> > Date: Monday, January 26, 2009, 11:20 AM > Hi, > > Thanks for the feedback, if you have any suggestions I am > open to them. I was thinking of something like. > > > public class Tuple { > > @Attribute > private String name; > > @Element > private String value; > > public Tuple(@Inject String name, @Inject String value) > { > this.name = name; > this.value = value; > } > } > > This would make it readable and writable. Taking the > parameters and seeing where they can be injected. This would > be easy to write. > > Niall > > > --- On Mon, 1/26/09, Kevin Day > <for...@tr...> wrote: > > > From: Kevin Day <for...@tr...> > > Subject: Re: [Simple-support] Using constructors with > arguments > > To: sim...@li... > > Date: Monday, January 26, 2009, 10:51 AM > > Thanks for taking a look. I may be trying to use this > > framework for more than what it is intented to do. If > you > > are interested in pursuing some use-cases, I'd be > happy > > to work with you on aspects of the design, etc... But > I > > also understand that different projects have different > > goals, and direct encapsulation of business layer > objects > > (which are more likely to be required to be immutable) > may > > not be part of the goal of Simple-XML. > > > > Using the @Commit or a combination of > @Replace/@Resolve > > requires an aweful lot of coding that it seems a > persistence > > framework could address... Coding with the @Commit, > etc... > > style is roughly similar to using a JAXB generated > object > > structure for persistence, then having a bunch of > > translators written to convert persistent values into > > business objects and vice-versa. It can be done, but > > I'm looking for something a lot more elegant. > > > > > > I'm also fine with using a Strategy to achieve the > goal > > (I've implemented a really rough first cut at this > > already), but there may be a couple of challenges. > > > > As an example, my work so far indicates that the > Strategy > > interface can provide a hook for instantiation of > objects > > (i.e. via a factory that could use injected parameters > from > > a DI container) - however, unless I'm missing > something, > > it doesn't look like Strategy has access to the > Type > > objects generated from parsing the XML tree, which > means > > that I can't use objects recovered from the > > deserialization during instantiation. If the objects > are > > simple (String or something easily handled with the > > *Transform classes), then this is no big deal (we can > just > > instantiate from the Type object in the node map), but > for > > complicated objects, I'm not sure how to handle > it. > > > > This makes me wonder if I'm trying to get Strategy > to > > do something that it just isn't designed to do > (maybe > > this kind of thing should be implemented using a > different > > layer of the API), or if I can somehow use the map > passed > > into the getElement method to make this work. > > > > > > So, is it possible that the Instantiator class is the > place > > where this functionality needs to take place? If so, > then > > the Instantiator would need to have access to the > > deserialization's context during the call to > getType(). > > For example, if there were some way to obtain named > Type > > objects for the fields/values of the object being > > deserialized? These could be used to instantiate > values > > that could then be passed to a factory or constructor. > I > > suspect this would involve making a read-only view of > the > > Collector available to Instantiator. > > > > I'm not sure how much control Simple has over the > > *order* that instantiation occurs in, or whether this > would > > impact things. It appears that Simple builds the Type > > hierarchy before it starts instantiating objects, so > that > > should be OK (unless there is a cyclic reference in > the > > constructor parameters - but that won't happen in > a well > > designed object hierarchy :-) ) > > > > I'm wondering if you have a philosophical overview > of > > the Simple architecture captured anywhere? The > JavaDocs > > don't really provide a high level overview, and > the API > > has a *lot* of layers to it that make it difficult for > > someone new the source to get a handle on what types > of > > behavior should be implemented at which level. My > > assumption is that the system takes several logical > passes > > over the object hierarchy: > > > > Parse XML into nodes > > For each node, obtain it's Type (this is the job > of > > Strategy I think?) > > Determine the class for each Type and determine > it's > > fields/parameters/etc... and create Contacts for those > (this > > is the job of Scanner I think? And that interacts > with the > > Collector somehow) > > Use each Type to instantiate a concrete object and > inject > > it into the Contacts (I think the Collector does this) > > > > Is that approximately correct? > > > > - K > > > > > > > > > > > > > > > > ----------------------- Original Message > > ----------------------- > > > > From: <Nia...@ub...> > > To: <for...@tr...>, > > <sim...@li...> > > Cc: > > Date: Mon, 26 Jan 2009 09:11:54 -0000 > > Subject: RE: [Simple-support] Using constructors with > > arguments > > > > Hi, > > > > Ill take a look at the read resolve and write replace > > issues you > > mention. The reason @Replace and @Resolve do not work > in > > lists is they > > go through the Traverser object, rather than the > Composite > > object > > directly. This is something I will have to address. So > > there are two > > options, the first is to use a strategy (there should > be > > plenty of > > examples in the test cases), the second is to use > @Commit > > to build the > > Tuples like so. > > > > public class TupleDatabase { > > > > private List<Tuple> tuples; > > > > @ElementList > > private List<TupleEntry> entries; > > > > @Commit > > private void commit() { > > for(TupleEntry entry : entries) { > > tuples.add(entry.name, entry.value); > > } > > } > > > > @Root > > private static class TupleEntry { > > @Element String name; > > @Element String value; > > } > > } > > > > Here when building the list you can create the tuples > > without a no-arg > > constructor. > > > > Hope this helps, > > Niall > > > > -----Original Message----- > > From: Kevin Day [mailto:for...@tr...] > > Sent: 24 January 2009 00:21 > > To: sim...@li... > > Subject: Re: [Simple-support] Using constructors with > > arguments > > > > Thanks for the suggestion, this type of strategy is > exactly > > what we do > > with our current Java serialization based persistence, > so > > it's easy to > > relate to (even though there's a lot of duplicate > > code). > > > > > > For some reason, though, @Replace isn't working > (the > > getSubstitute() > > method is never called). > > > > After a bit of digging into the source, I think that > the > > problem is that > > the only place that Caller#replace() is actually > called is > > in > > Composite#writeReplace(). And that method is only > called > > for composite > > objects. We are dealing with a list of objects, so it > > seems that maybe > > writeReplace() hasn't been properly implemented > for > > ElementList > > handlers? > > > > If I place my object outside the list (as part of a > > composite element), > > then it serializes fine. > > > > > > Another issue I'm running into is during > > deserialization. In this case, > > I am using @Resolve on the replaced object (which is > part > > of a composite > > object structure). I set a break point on > > Composite.readResolve(), but > > readResolve never gets called. The framework throws > an > > InstantiationException from Factory#getOverride(). > > > > > > I'm not sure if the problem here is my lack of > > understanding of the API, > > or if this is just a corner case that didn't get > unit > > testing written > > for it. I am attaching a self contained unit test > case > > that exhibits > > all of the above behavior. Please let me know if you > have > > any > > pointers/suggestions, or if I may just be missing > > something! > > > > Cheers, > > > > - Kevin > > > > > > PS - I suspect that the use of @Replace and @Resolve > may > > not solve our > > entire use case, but it is a great start at a solution > and > > is helping me > > understand the Simple framework better. Our ultimate > need > > also includes > > injection of resources via a DI framework, and I'm > > having a hard time > > figuring out how that's going to happen without > using > > some sort of > > factory instantiation strategy (I suppose that we > could use > > a singleton > > to get the DI hook, but that's an anti-design > pattern > > that I really > > would prefer to avoid at all costs). Hopefully we can > > discuss this > > aspect a bit more after I understand why my @Replace > and > > @Resolve aren't > > working! > > > > > > > > > > > > ----------------------- Original Message > > ----------------------- > > > > From: <Nia...@ub...> > > To: <for...@tr...>, > > <sim...@li...> > > Cc: > > Date: Thu, 22 Jan 2009 16:45:15 -0000 > > Subject: RE: [Simple-support] Using constructors with > > arguments > > > > Hi, > > > > There is no need to do this. You can do the following. > > > > @Root > > public class Tuple { > > > > final private String from; > > final private String to; > > > > public Tuple(String from, String to){ > > this.from = from; > > this.to = to; > > } > > > > @Replace > > private TupleSubstitute getSubstitute() { > > return new TupleSubstitute(from, to); > > } > > > > public String getFrom() { > > return from; > > } > > > > public String getTo() { > > return to; > > } > > > > public String toString() { > > return from + " -> " + to; > > } > > > > } > > > > @Root > > private class TupleSubstitute { > > > > @Element > > private String from; > > @Element > > private String to; > > > > public TupleSubstitute() { > > super(); > > } > > > > public TupleSubstitute(String from, String to) { > > this.from = from; > > this.to = to; > > } > > > > @Resolve > > public Tuple getTuple() { > > return new Tuple(); > > } > > } > > > > This should work, for you. The @Resolve annotation > resolves > > the > > deserialized object before assigning it to the field > or > > method. The > > @Replace object replaces the object in the stream. > Just > > like java object > > serialization. Let me know how this works out for you. > > > > Hope this helps, > > Niall > > > > > > > > -----Original Message----- > > From: Kevin Day [mailto:for...@tr...] > > Sent: 21 January 2009 22:56 > > To: Simple (Java Project) > > Subject: Re: [Simple-support] Using constructors with > > arguments > > > > I've done some additional work on handling classes > that > > do not have > > zero-arg constructors. First, I've put together > some > > simple sample code > > (attached, start with TryIt#main) that shows one of > the > > situations we > > are facing: we have a number of immutable Tuple > objects > > that we need to > > serialize/deserialze. The values used in the Tuple > > class' constructor > > come from attributes (or elements) from the XML. The > > attached > > serializes fine, but we can't deserialize it b/c > of the > > lack of > > no-argument constructor. We can't add a no-arg > > constructor because the > > class is intended to be immutable (in fact, the fields > are > > marked as > > final). In addition, the sample code shows the Tuple > > values as holding > > simple strings - but in our application, the values > are > > going to be > > complex objects. > > > > > > I have put together a Strategy and Type implementation > that > > *kind* of > > works, but I'm running into some issues (may be > related > > to my lack of > > familiarity with the code base). > > > > The approach that I'm working on now creates a new > > Strategy that allows > > us to register special Type objects that can handle > object > > instantiation > > based on state of the deserialization process (for > now, > > I'm calling this > > FactoryGeneratedStrategy). Ideally, > > FactoryGeneratedStrategy would be > > able to inter-operate with any other Strategy > > (DefaultStrategy, > > CycleStrategy, TreeStrategy) - after all, it's > only > > purpose is to help > > instantiate objects during deserialization - the > behavior > > of the other > > strategies is still desirable. > > > > I ran into a couple of problems with this type of > Strategy > > chaining > > approach: > > > > 1. DefaultStrategy is not instantiable due to package > > scope visibility > > (this is the smaller issue) 2. The other strategies > appear > > to be > > implemented in a way that assumes use of zero-arg > > constructors. For > > example, CycleStrategy#getElement returns an Allocate > > object depending > > on the deserialization state. The Allocate object is > > ultimately backed > > by an Instance object as it's delegate Type. > Instance > > assumes a > > zero-arg constructor. > > > > > > Short of re-implementing all of the *Strategy classes, > I > > can't see how > > to go about providing a factory to create new object > > instances (without > > losing functionality provided by various Strategy > classes). > > > > > > My initial impression based on the above is that > Strategy > > may not be the > > appropriate place in the hierarchy to add object > > instantiation behavior. > > If not, where? The Instantiator class seems a likely > > candidate, except > > that it's getInstace() method doesn't have > access > > to deserialization > > context information. > > > > > > > > Maybe I'm just going about this all wrong... If > anyone > > can provide some > > suggestions, I'd love to hear them! > > > > > > Thanks, > > > > - K > > > > > > ----------------------- Original Message > > ----------------------- > > > > From: Kevin Day <ke...@tr...> > > To: Simple (Java Project) > > <sim...@li...> > > Cc: > > Date: Tue, 20 Jan 2009 17:28:05 -0700 > > Subject: [Simple-support] Using constructors with > arguments > > > > For starters, I really like what I see in this project > > (just started > > reviewing it this afternoon). I'm hoping that I > can > > get some pointers > > on a specific use-case. > > > > > > I would like to use Simple in conjunction with a > dependency > > injection > > system (probably Guice) and List implementations from > the > > GlazedLists > > project. > > > > We have to use a constructor on our list > implementations > > that contains > > arguments (some of the arguments provided by Guice, > some > > from element or > > attribute data in the XML). > > > > What is the best way to approach this with Simple? > > > > It seems that some sort of Strategy mixed with a > custom > > Type is in > > order, but I'm not entirely clear on the best > approach. > > The > > architecture of the framework looks powerful enough to > do > > what we need, > > but I can't see where to get started just yet. > > > > > > To give a pseudo-code example of what we are trying to > do > > (in real life, > > we'll be injecting SomeInjectedObject using Guice > or a > > factory/service > > provider call): > > > > class SpecialList<E>{ > > public SpecialList(SomeInjectedObject injected, String > > valueFromAttribute, SomeObject valueFromElement){ ... > > } > > } > > > > > > class MyObject{ > > @ElementList > > SpecialList<ElementObject> list = new > > > SpecialList<ElementObject>(SomeInjectedObject.defaultInstance, > > "test", > > new SomeObject()); > > > > } > > > > > > When we serialize this with Simple, we'd like to > see > > something > > approximately like the following: > > > > <myObject valueFromAttribute="test"> > > <someObject> ... </someObject> > > <list> > > <elementObject> ... whatever goes into this ... > > </elementObject> > > <elementObject> ... whatever goes into this ... > > </elementObject> ... > > </list> > > </myObject> > > > > > > Note that: > > > > 1. The <list> element doesn't have a class > > attribute 2. When we > > construct the list during deserialization, we need to > be > > able to pull > > the 'valueFromAttribute' and > 'someObject' > > values to use during > > construction of the SpecialList object 3. The > SpecialList > > object needs > > to have the 3 argument constructor called (not a > zero-arg > > constructor). > > And it is not possible to call a zero arg constructor, > then > > modify the > > object afterwards to get the same result. > > > > > > Any pointers? I may be pushing the framework too hard > > (some of the > > above requirements can be relaxed - if it isn't > > possible to obtain > > valueFromAttribute or someObject at construction time, > we > > can find > > workarounds - but we have to be able to create the > > SpecialList instance > > using values from a factory/Guice/etc...). For what > > it's worth, we have > > this type of behavior working in Betwixt using custom > > BeanCreator > > implementations. > > > > Thanks much, > > > > - Kevin > > > ------------------------------------------------------------------------ > > ------ > > This SF.net email is sponsored by: > > SourcForge Community > > SourceForge wants to tell your story. > > http://p.sf.net/sfu/sf-spreadtheword > > > > > > _______________________________________________ > > Simple-support mailing list > > Sim...@li... > > > https://lists.sourceforge.net/lists/listinfo/simple-support > > Visit our website at http://www.ubs.com > > > > This message contains confidential information and is > > intended only for > > the individual named. If you are not the named > addressee > > you should not > > disseminate, distribute or copy this e-mail. Please > notify > > the sender > > immediately by e-mail if you have received this e-mail > by > > mistake and > > delete this e-mail from your system. > > > > E-mails are not encrypted and cannot be guaranteed to > be > > secure or > > error-free as information could be intercepted, > corrupted, > > lost, > > destroyed, arrive late or incomplete, or contain > viruses. > > The sender > > therefore does not accept liability for any errors or > > omissions in the > > contents of this message which arise as a result of > e-mail > > transmission. > > > > If verification is required please request a hard-copy > > version. This > > message is provided for informational purposes and > should > > not be > > construed as a solicitation or offer to buy or sell > any > > securities or > > related financial instruments. > > > > UBS Limited is a company registered in England & > Wales > > under company > > number 2035362, whose registered office is at 1 > Finsbury > > Avenue, London, > > EC2M 2PP, United Kingdom. > > > > UBS AG (London Branch) is registered as a branch of a > > foreign company > > under number BR004507, whose registered office is at > > 1 Finsbury Avenue, London, EC2M 2PP, United Kingdom. > > > > UBS Clearing and Execution Services Limited is a > company > > registered in > > England & Wales under company number 03123037, > whose > > registered office > > is at 1 Finsbury Avenue, London, EC2M 2PP, United > Kingdom. > > Visit our website at http://www.ubs.com > > > > This message contains confidential information and is > > intended only > > for the individual named. If you are not the named > > addressee you > > should not disseminate, distribute or copy this > e-mail. > > Please > > notify the sender immediately by e-mail if you have > > received this > > e-mail by mistake and delete this e-mail from your > system. > > > > E-mails are not encrypted and cannot be guaranteed to > be > > secure or > > error-free as information could be intercepted, > corrupted, > > lost, > > destroyed, arrive late or incomplete, or contain > viruses. > > The sender > > therefore does not accept liability for any errors or > > omissions in the > > contents of this message which arise as a result of > e-mail > > transmission. > > If verification is required please request a hard-copy > > version. This > > message is provided for informational purposes and > should > > not be > > construed as a solicitation or offer to buy or sell > any > > securities > > or related financial instruments. > > > > UBS Limited is a company registered in England & > Wales > > under company > > number 2035362, whose registered office is at 1 > Finsbury > > Avenue, > > London, EC2M 2PP, United Kingdom. > > > > UBS AG (London Branch) is registered as a branch of a > > foreign company > > under number BR004507, whose registered office is at > > 1 Finsbury Avenue, London, EC2M 2PP, United Kingdom. > > > > UBS Clearing and Execution Services Limited is a > company > > registered > > in England & Wales under company number 03123037, > whose > > registered > > office is at 1 Finsbury Avenue, London, EC2M 2PP, > United > > Kingdom. > > > > > ------------------------------------------------------------------------------ > > This SF.net email is sponsored by: > > SourcForge Community > > SourceForge wants to tell your story. > > http://p.sf.net/sfu/sf-spreadtheword > > _______________________________________________ > > Simple-support mailing list > > Sim...@li... > > > https://lists.sourceforge.net/lists/listinfo/simple-support > > > > > ------------------------------------------------------------------------------ > This SF.net email is sponsored by: > SourcForge Community > SourceForge wants to tell your story. > http://p.sf.net/sfu/sf-spreadtheword > _______________________________________________ > Simple-support mailing list > Sim...@li... > https://lists.sourceforge.net/lists/listinfo/simple-support |