You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(4) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(3) |
Feb
(4) |
Mar
(1) |
Apr
(5) |
May
|
Jun
(3) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(2) |
Dec
(6) |
2006 |
Jan
(1) |
Feb
(6) |
Mar
(9) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(12) |
2007 |
Jan
(44) |
Feb
(36) |
Mar
(24) |
Apr
(59) |
May
(6) |
Jun
|
Jul
|
Aug
|
Sep
(3) |
Oct
(2) |
Nov
(4) |
Dec
(3) |
2008 |
Jan
(34) |
Feb
(4) |
Mar
|
Apr
|
May
|
Jun
(4) |
Jul
|
Aug
(7) |
Sep
(2) |
Oct
|
Nov
(3) |
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(5) |
Nov
|
Dec
|
2010 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Ben A. <ben...@ac...> - 2007-01-20 01:17:38
|
Matt Sgarlata wrote: > One situation I was considering is if you are doing something simple > like Morph.convertToInteger("13asdf") you want a TransformationException > instead of a JDK NumberFormatException. This would be in the interest > of hiding implementation details of a particular transformer from a > user. Fortunately, it appears the transformers happen to be written > such that this is exactly what happens even with your change. Of course > I will need to do testing to verify this is the case. Hi Matt If any transformer explicitly throws TransformationException, the patch still propagates it up. That's probably why you're seeing the behavior with convertToInteger (although not 100%, I haven't looked at the code). All the patch does is modify all instances of "new MorphException(Exception)" so that if the Exception is a RuntimeException, throw RuntimeException directly. At no point does the patch unwrap a TransformationException, opting instead to avoid creating them in the first place. Cheers Ben |
From: Matt S. <Mat...@wh...> - 2007-01-20 01:02:48
|
Thanks for the detailed explanations. I am leaning towards accepting the patches but I would like to sleep on it. One situation I was considering is if you are doing something simple like Morph.convertToInteger("13asdf") you want a TransformationException instead of a JDK NumberFormatException. This would be in the interest of hiding implementation details of a particular transformer from a user. Fortunately, it appears the transformers happen to be written such that this is exactly what happens even with your change. Of course I will need to do testing to verify this is the case. I also like the idea of "if it's a Morph error, throw a Morph exception, otherwise rethrow the exception that actually occurred". When I first started really using Morph that was one of the things that confused me too, even though I wrote the framework: I would see MorphExceptions and think it was a bug in Morph when in reality the issue lied elsewhere. Matt Ben Alex wrote: > Alan Stewart wrote: > >> We're using Morph now at Woolworths as the "Assembler" implementation in >> ROO to transform between rich domain object and DTO. If I have to catch >> a TransformationException (that wraps our business exception) in an MVC >> controller, it means we're tied to that implementation. If for what ever >> reason we swapped Dozer or a different implementation back in as the >> Assembler, then the controllers break. I believe architecturally it >> would be more pure not to have the Morph exceptions in client code. >> > > Hi Matt and Alan > > Pros of keeping TransformationException wrapping RuntimeExceptions: > > * Can determine Morph called the method which caused the exception. > Mitigating factors: (i) introspect the stack trace and find it out that > way; (ii) not a common requirement in my experience to know this anyway. > > Cons of keeping TransformationException wrapping RuntimeExceptions: > > * Morph leaks out beyond the assembly layer, as you are *forced* to > catch a Morph-specific exception type in order to extract the nested > RuntimeException. Mitigating factor: at least you can put such code into > a static method. > > * Try...Catch blocks become more lengthy and complex, as they need to > handle the TransformationException in a special manner (either directly > or via a static method). > > * Becomes harder to debug and figure out what is happening. Having the > untouched RuntimeException propagate through the control flow is the > simplest solution. This means less user support from people unable to > figure out what went wrong and are incorrectly attributing failure to > Morph or trying to adjust configuration settings to fix what on the > surface appears like a "Morph related problem". Less community support > will be necessary if TransformationExceptions don't wrap > RuntimeException, especially given general moves to RuntimeExceptions > means a good number of users will be employing them anyway (and those > employing checked exceptions will reasonably expect to have to deal with > a nested exception - a side-effect of their checked exception choice). > > * Correct me if I am wrong, but Dozer doesn't force you to deal with its > own exception hierarchy. Alan can confirm this, but I'm 99% sure. So on > a competitive level, it seems desirable to follow the lead of the bigger > project if users are ever expected to easily transition from Dozer. > > I may have missed something. Look forward to your thoughts. > > Cheers > Ben > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > > |
From: Ben A. <ben...@ac...> - 2007-01-19 23:53:05
|
Alan Stewart wrote: > We're using Morph now at Woolworths as the "Assembler" implementation in > ROO to transform between rich domain object and DTO. If I have to catch > a TransformationException (that wraps our business exception) in an MVC > controller, it means we're tied to that implementation. If for what ever > reason we swapped Dozer or a different implementation back in as the > Assembler, then the controllers break. I believe architecturally it > would be more pure not to have the Morph exceptions in client code. Hi Matt and Alan Pros of keeping TransformationException wrapping RuntimeExceptions: * Can determine Morph called the method which caused the exception. Mitigating factors: (i) introspect the stack trace and find it out that way; (ii) not a common requirement in my experience to know this anyway. Cons of keeping TransformationException wrapping RuntimeExceptions: * Morph leaks out beyond the assembly layer, as you are *forced* to catch a Morph-specific exception type in order to extract the nested RuntimeException. Mitigating factor: at least you can put such code into a static method. * Try...Catch blocks become more lengthy and complex, as they need to handle the TransformationException in a special manner (either directly or via a static method). * Becomes harder to debug and figure out what is happening. Having the untouched RuntimeException propagate through the control flow is the simplest solution. This means less user support from people unable to figure out what went wrong and are incorrectly attributing failure to Morph or trying to adjust configuration settings to fix what on the surface appears like a "Morph related problem". Less community support will be necessary if TransformationExceptions don't wrap RuntimeException, especially given general moves to RuntimeExceptions means a good number of users will be employing them anyway (and those employing checked exceptions will reasonably expect to have to deal with a nested exception - a side-effect of their checked exception choice). * Correct me if I am wrong, but Dozer doesn't force you to deal with its own exception hierarchy. Alan can confirm this, but I'm 99% sure. So on a competitive level, it seems desirable to follow the lead of the bigger project if users are ever expected to easily transition from Dozer. I may have missed something. Look forward to your thoughts. Cheers Ben |
From: Alan S. <ala...@op...> - 2007-01-19 23:30:43
|
Hi Matt, We're using Morph now at Woolworths as the "Assembler" implementation in ROO to transform between rich domain object and DTO. If I have to catch a TransformationException (that wraps our business exception) in an MVC controller, it means we're tied to that implementation. If for what ever reason we swapped Dozer or a different implementation back in as the Assembler, then the controllers break. I believe architecturally it would be more pure not to have the Morph exceptions in client code. Regards Alan Matt Sgarlata wrote: > Hi Ben - > > Before adopting the change to not wrap RuntimeExceptions as > TransformationExceptions, I would like to discuss the pros and cons of > this change in greater detail. To me, the benefit of wrapping these > exceptions as TransformationExceptions is that higher up the stack you > know that an error occurred while a Morph transformation was being > performed, as opposed to an error happening in Hibernate or some other > library or an error happening in higher level objects that are > directly servicing client requests (MVC controllers, Swing Actions, etc) > > I can understand that if you've gone to the trouble of introducing > your own business exceptions that you want to work with those > exceptions rather than Morph's exceptions. However, couldn't you just > catch the MorphException and retrieve its cause with a call to > getCause() ? Or is the issue that in a nested transformation you end > up with your business exceptions being buried 3 or 4 exceptions deep? > If that's the problem, I propose what we should do is change Morph so > that it doesn't wrap its own exceptions 3 or 4 deep, or that if it > does do so, it at least has an easy way to reference the first > original non-Morph exception. Perhaps we could introduce a new method > called getFirstCause or something similar. > > Matt S > > Ben Alex wrote: >> Hi all >> >> Please find attached another patch. >> >> It fixes a bug introduced in recent changes to ContainerCopier. It was >> the same bug we saw earlier this month, being building with Ant requires >> casting ternary operators. >> >> I've also modified BaseTransformer to NOT wrap RuntimeExceptions in a >> TransformationException. This is really critical for us. If we have a >> mutator method throw SomeBusinessException which extends >> RuntimeException, it's necessary that SomeBusinessException is what >> Morph eventually returns - not wrapped in a TransformationException. >> There's no technical need for it in the case of a RuntimeException, so >> that attached patch provides this enhancement. I hope you agree with >> this change. >> >> Cheers >> Ben >> >> ------------------------------------------------------------------------ >> >> >> Property changes on: /home/balex/workspace/morph >> ___________________________________________________________________ >> Name: svn:ignore >> + >> dist >> target >> build >> >> >> Index: /home/balex/workspace/morph/src/core/net/sf/morph/transform/copiers/ContainerCopier.java >> =================================================================== >> --- /home/balex/workspace/morph/src/core/net/sf/morph/transform/copiers/ContainerCopier.java (revision 94) >> +++ /home/balex/workspace/morph/src/core/net/sf/morph/transform/copiers/ContainerCopier.java (working copy) >> @@ -207,7 +207,7 @@ >> // final Iterator that will be returned to the user of the >> // ContainerCopier >> Iterator iterator = getContainerReflector().getIterator(source); >> - return iter ? iterator : new IteratorEnumeration(iterator); >> + return iter ? iterator : (Object) new IteratorEnumeration(iterator); >> } >> return super.convertImpl(destinationClass, source, locale); >> } >> Index: /home/balex/workspace/morph/src/core/net/sf/morph/transform/transformers/BaseTransformer.java >> =================================================================== >> --- /home/balex/workspace/morph/src/core/net/sf/morph/transform/transformers/BaseTransformer.java (revision 94) >> +++ /home/balex/workspace/morph/src/core/net/sf/morph/transform/transformers/BaseTransformer.java (working copy) >> @@ -127,8 +127,9 @@ >> } >> catch (TransformationException e) { >> throw e; >> - } >> - catch (StackOverflowError e) { >> + } catch (RuntimeException e) { >> + throw (RuntimeException) e; >> + } catch (StackOverflowError e) { >> throw new TransformationException( >> "Stack overflow detected. This usually occurs when a transformer implements " >> + ObjectUtils.getObjectDescription(ExplicitTransformer.class) >> @@ -234,8 +235,9 @@ >> } >> catch (TransformationException e) { >> throw e; >> - } >> - catch (Exception e) { >> + } catch (RuntimeException e) { >> + throw (RuntimeException) e; >> + } catch (Exception e) { >> throw new TransformationException( >> "Could not initialize transformer " >> + ObjectUtils.getObjectDescription(this), e); >> @@ -296,11 +298,11 @@ >> >> try { >> return convertImpl(destinationClass, source, locale); >> - } >> - catch (TransformationException e) { >> + } catch (TransformationException e) { >> throw (TransformationException) e; >> - } >> - catch (Throwable t) { >> + } catch (RuntimeException e) { >> + throw (RuntimeException) e; >> + } catch (Throwable t) { >> if (isTransformable(destinationClass, ClassUtils.getClass(source))) { >> throw new TransformationException(destinationClass, source, t); >> } >> @@ -392,8 +394,9 @@ >> } >> catch (TransformationException e) { >> throw e; >> - } >> - catch (Exception e) { >> + } catch (RuntimeException e) { >> + throw (RuntimeException) e; >> + } catch (Exception e) { >> if (isTransformable(destination.getClass(), source.getClass())) { >> throw new TransformationException("Error copying source " >> + ObjectUtils.getObjectDescription(source) + " to destination " >> >> ------------------------------------------------------------------------ >> >> ------------------------------------------------------------------------- >> Take Surveys. Earn Cash. Influence the Future of IT >> Join SourceForge.net's Techsay panel and you'll get the chance to share your >> opinions on IT & business topics through brief surveys - and earn cash >> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV >> ------------------------------------------------------------------------ >> >> _______________________________________________ >> morph-developer mailing list >> mor...@li... >> https://lists.sourceforge.net/lists/listinfo/morph-developer >> > > ------------------------------------------------------------------------ > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > ------------------------------------------------------------------------ > > _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > |
From: Matt S. <Mat...@wh...> - 2007-01-19 17:00:59
|
Hi Ben - Before adopting the change to not wrap RuntimeExceptions as TransformationExceptions, I would like to discuss the pros and cons of this change in greater detail. To me, the benefit of wrapping these exceptions as TransformationExceptions is that higher up the stack you know that an error occurred while a Morph transformation was being performed, as opposed to an error happening in Hibernate or some other library or an error happening in higher level objects that are directly servicing client requests (MVC controllers, Swing Actions, etc) I can understand that if you've gone to the trouble of introducing your own business exceptions that you want to work with those exceptions rather than Morph's exceptions. However, couldn't you just catch the MorphException and retrieve its cause with a call to getCause() ? Or is the issue that in a nested transformation you end up with your business exceptions being buried 3 or 4 exceptions deep? If that's the problem, I propose what we should do is change Morph so that it doesn't wrap its own exceptions 3 or 4 deep, or that if it does do so, it at least has an easy way to reference the first original non-Morph exception. Perhaps we could introduce a new method called getFirstCause or something similar. Matt S Ben Alex wrote: > Hi all > > Please find attached another patch. > > It fixes a bug introduced in recent changes to ContainerCopier. It was > the same bug we saw earlier this month, being building with Ant requires > casting ternary operators. > > I've also modified BaseTransformer to NOT wrap RuntimeExceptions in a > TransformationException. This is really critical for us. If we have a > mutator method throw SomeBusinessException which extends > RuntimeException, it's necessary that SomeBusinessException is what > Morph eventually returns - not wrapped in a TransformationException. > There's no technical need for it in the case of a RuntimeException, so > that attached patch provides this enhancement. I hope you agree with > this change. > > Cheers > Ben > > ------------------------------------------------------------------------ > > > Property changes on: /home/balex/workspace/morph > ___________________________________________________________________ > Name: svn:ignore > + > dist > target > build > > > Index: /home/balex/workspace/morph/src/core/net/sf/morph/transform/copiers/ContainerCopier.java > =================================================================== > --- /home/balex/workspace/morph/src/core/net/sf/morph/transform/copiers/ContainerCopier.java (revision 94) > +++ /home/balex/workspace/morph/src/core/net/sf/morph/transform/copiers/ContainerCopier.java (working copy) > @@ -207,7 +207,7 @@ > // final Iterator that will be returned to the user of the > // ContainerCopier > Iterator iterator = getContainerReflector().getIterator(source); > - return iter ? iterator : new IteratorEnumeration(iterator); > + return iter ? iterator : (Object) new IteratorEnumeration(iterator); > } > return super.convertImpl(destinationClass, source, locale); > } > Index: /home/balex/workspace/morph/src/core/net/sf/morph/transform/transformers/BaseTransformer.java > =================================================================== > --- /home/balex/workspace/morph/src/core/net/sf/morph/transform/transformers/BaseTransformer.java (revision 94) > +++ /home/balex/workspace/morph/src/core/net/sf/morph/transform/transformers/BaseTransformer.java (working copy) > @@ -127,8 +127,9 @@ > } > catch (TransformationException e) { > throw e; > - } > - catch (StackOverflowError e) { > + } catch (RuntimeException e) { > + throw (RuntimeException) e; > + } catch (StackOverflowError e) { > throw new TransformationException( > "Stack overflow detected. This usually occurs when a transformer implements " > + ObjectUtils.getObjectDescription(ExplicitTransformer.class) > @@ -234,8 +235,9 @@ > } > catch (TransformationException e) { > throw e; > - } > - catch (Exception e) { > + } catch (RuntimeException e) { > + throw (RuntimeException) e; > + } catch (Exception e) { > throw new TransformationException( > "Could not initialize transformer " > + ObjectUtils.getObjectDescription(this), e); > @@ -296,11 +298,11 @@ > > try { > return convertImpl(destinationClass, source, locale); > - } > - catch (TransformationException e) { > + } catch (TransformationException e) { > throw (TransformationException) e; > - } > - catch (Throwable t) { > + } catch (RuntimeException e) { > + throw (RuntimeException) e; > + } catch (Throwable t) { > if (isTransformable(destinationClass, ClassUtils.getClass(source))) { > throw new TransformationException(destinationClass, source, t); > } > @@ -392,8 +394,9 @@ > } > catch (TransformationException e) { > throw e; > - } > - catch (Exception e) { > + } catch (RuntimeException e) { > + throw (RuntimeException) e; > + } catch (Exception e) { > if (isTransformable(destination.getClass(), source.getClass())) { > throw new TransformationException("Error copying source " > + ObjectUtils.getObjectDescription(source) + " to destination " > > ------------------------------------------------------------------------ > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > ------------------------------------------------------------------------ > > _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > |
From: Alan S. <ala...@op...> - 2007-01-19 11:12:36
|
Hi, Ben's patch to allow us to throw runtime business exceptions from our domain objects and not have them wrapped as TransformationExceptions. I tested it today and all works fine. I hope this patch and all other of Ben's recent suggestions and changes can make it into the next release of Morph. Cheers Alan |
From: Ben A. <ben...@ac...> - 2007-01-19 06:56:24
|
Hi all Please find attached another patch. It fixes a bug introduced in recent changes to ContainerCopier. It was the same bug we saw earlier this month, being building with Ant requires casting ternary operators. I've also modified BaseTransformer to NOT wrap RuntimeExceptions in a TransformationException. This is really critical for us. If we have a mutator method throw SomeBusinessException which extends RuntimeException, it's necessary that SomeBusinessException is what Morph eventually returns - not wrapped in a TransformationException. There's no technical need for it in the case of a RuntimeException, so that attached patch provides this enhancement. I hope you agree with this change. Cheers Ben |
From: Matt B. <gud...@ya...> - 2007-01-15 23:58:43
|
As threatened, I've added in SVN HEAD an implementation of an AssemblerCopier loosely based on a backward version of the existing MultipleDestinationConverter. Tomorrow I hope to rewrite MDC as a DisassemblerCopier, also as threatened. Stay tuned, Matt (B) ____________________________________________________________________________________ Do you Yahoo!? Everyone is raving about the all-new Yahoo! Mail beta. http://new.mail.yahoo.com |
From: Matt B. <gud...@ya...> - 2007-01-15 23:55:46
|
Hi Ben, Great suggestions. Hopefully we'll be following through on these. Thanks for the exhaustive (in a good way) analysis; I had come to similar conclusions prior to jumping the Dozer ship, but haven't really put Morph through its paces in more serious settings yet. -Matt --- Ben Alex <ben...@ac...> wrote: > Hi Matt > > Matt Benson wrote: > > > I have just committed your patch (with IIRC one > > spelling correction) to HEAD. > > Thanks. > > > So how are you finding Morph compared to Dozer so > far? > > To compare and contrast, my interpretation of the > two projects is: > > Community size: Dozer is bigger > Release frequency: Dozer is more frequent > Download numbers: Dozer higher (6400 versus about > 520) > Version control: Dozer uses SourceForge (Morph is > still public, though) > Googlability: Dozer more easily found ("assembly", > "assembler" etc) > Documentation: Dozer has more reference and web site > documentation > Patch receptiveness: Both the Morph and Dozer > communities are welcoming > Configuration: Morph is 100% Spring configurable > Architecture: Morph resonated with me > Flexibility: Morph has proven very flexible for our > needs > Bugs: Morph hasn't had any that we have found * > Logo and font on web site: Okay, okay, I'll stop > now... :-) > > * We have an Assembler interface which is used in a > number of projects. > To make Dozer work as we needed, we found a number > of bugs that required > patching in Dozer (which to their credit were > applied expeditiously). > Morph implemented the interface and passed the same > unit tests without > any bugs being found. That's not to assert that > Morph is bug-free or > Dozer is buggy by any means. It is simply asserting > that for our usage > patterns, unit tests and Assembler interface, we > found bugs in Dozer and > no bugs in Morph when being used an identical (and > complex) way. > > So, to sum it up, Dozer wins on the > community-related dimensions whereas > Morph, in my assessment, is a higher quality > technical solution. I'd > suggest more frequent releases and documentation > would organically > resolve Morph's community size, download numbers and > Googlability. > > We also need to bear in mind that neither project is > phenomenally large > or well-known in the enterprise Java community. Most > Java developers > needing to do assembly write code by hand. Some > promotion of the role of > assembly in modern architecture would benefit both > projects. > > Cheers > Ben > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get > the chance to share your > opinions on IT & business topics through brief > surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > ____________________________________________________________________________________ Now that's room service! Choose from over 150,000 hotels in 45,000 destinations on Yahoo! Travel to find your fit. http://farechase.yahoo.com/promo-generic-14795097 |
From: Ben A. <ben...@ac...> - 2007-01-15 22:54:50
|
Hi Matt Matt Benson wrote: > I have just committed your patch (with IIRC one > spelling correction) to HEAD. Thanks. > So how are you finding Morph compared to Dozer so far? To compare and contrast, my interpretation of the two projects is: Community size: Dozer is bigger Release frequency: Dozer is more frequent Download numbers: Dozer higher (6400 versus about 520) Version control: Dozer uses SourceForge (Morph is still public, though) Googlability: Dozer more easily found ("assembly", "assembler" etc) Documentation: Dozer has more reference and web site documentation Patch receptiveness: Both the Morph and Dozer communities are welcoming Configuration: Morph is 100% Spring configurable Architecture: Morph resonated with me Flexibility: Morph has proven very flexible for our needs Bugs: Morph hasn't had any that we have found * Logo and font on web site: Okay, okay, I'll stop now... :-) * We have an Assembler interface which is used in a number of projects. To make Dozer work as we needed, we found a number of bugs that required patching in Dozer (which to their credit were applied expeditiously). Morph implemented the interface and passed the same unit tests without any bugs being found. That's not to assert that Morph is bug-free or Dozer is buggy by any means. It is simply asserting that for our usage patterns, unit tests and Assembler interface, we found bugs in Dozer and no bugs in Morph when being used an identical (and complex) way. So, to sum it up, Dozer wins on the community-related dimensions whereas Morph, in my assessment, is a higher quality technical solution. I'd suggest more frequent releases and documentation would organically resolve Morph's community size, download numbers and Googlability. We also need to bear in mind that neither project is phenomenally large or well-known in the enterprise Java community. Most Java developers needing to do assembly write code by hand. Some promotion of the role of assembly in modern architecture would benefit both projects. Cheers Ben |
From: Matt B. <gud...@ya...> - 2007-01-15 17:19:10
|
--- Ben Alex <ben...@ac...> wrote: > Ben Alex wrote: > > I've attached the patch (described in my last > post). It has been working > > fine here. > > Hi guys > > Any progress on this? I really need this > functionality in core. I've > been using the patch successfully for a few days > now. A further reason > we've found for supporting a modified > InstantiatingReflector is to > retrieve existing objects from a repository that we > want to decorate > with changes from an input DTO. There are therefore > several usage > scenarios which benefit from the "Object parameters" > additional > parameter on the interface method. > Hi Ben, I have just committed your patch (with IIRC one spelling correction) to HEAD. Sorry for the delay; I wanted to think about this first, because I was having a little trouble deciding whether this was the responsibility of the InstantiatingReflector, or that of a particular Transformer implementation. Finally I realized that (1) the Reflector exists at least partially (originally wholly I suppose) to facilitate conversions, and (2) if Constructor.newInstance() required the parameter (at least before varargs) then it is sensible for Morph to follow suit. Finally, as I mentioned in an earlier email, Morph is not as constrained by BC issues at present as are other software packages. So how are you finding Morph compared to Dozer so far? br, Matt > Cheers > Ben > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get > the chance to share your > opinions on IT & business topics through brief > surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > ____________________________________________________________________________________ The fish are biting. Get more visitors on your site using Yahoo! Search Marketing. http://searchmarketing.yahoo.com/arp/sponsoredsearch_v2.php |
From: Matt B. <gud...@ya...> - 2007-01-15 15:53:35
|
I'm replying to myself! :| --- Matt Benson <gud...@ya...> wrote: > Responses inline: > > --- Matt Sgarlata > <Mat...@wh...> wrote: > > Regarding the MultipleDestinationConverter, the > > final call in the class > > was probably supposed to be > > getContainerConverter().convert(destinationClass, > > *destinationObjects*, > > locale); I went ahead and made this change. This > > class was created > > because someone was challenging me that my > > interfaces only allowed 1 -> > > 1 object conversions as opposed to also allowing > one > > object to be broken > > into several smaller object or several smaller > > objects to be combined > > into 1 larger object. The idea here would be you > > had something like, > > say, a Person that you wanted to be converted into > a > > collection of > > smaller objects like PoliticalViews, BankAccount, > > Cars. Those 3 smaller > > objects would have to be returned as some type of > > collection, say as a > > List or an array of Object[]s. That was what the > > final call to > > getContainerConverter() was for. Really this is > > more of a hypothetical > > class to show that this type of thing was possible > > to my friend I was > > hoping would get involved in the project (didn't > > work). I don't > > anticipate anyone would actually use this class, > and > > I probably haven't > > even looked at it since the date it was first > > written. Perhaps we > > should just delete it? > > > No, I think it has a place. There's some Fowlerism > like "Assembly Pattern" or something that this > should > be an example of... Dozer explicitly mentions it in > their manual, so you're probably best off keeping it > for competitive reasons. We should just try to > document it better and provide examples. > Looked it up; it was an "Assembler" concept: http://www.martinfowler.com/eaaCatalog/dataTransferObject.html I still think we should support this. But since the class is in the copiers package, maybe we should rename it DisassemblerCopier or something? Then we can complement it with an AssemblerCopier that copies multiple source objects onto a single destination object... tell you what, if you don't like it, let me know. :) > Does this mean CombiningCopier was meant as the > opposite of MultipleDestinationConverter? > Ignore that question: I wasn't looking at anything, and just remembered the classname. ;) That would be the AssemblerCopier I mentioned above. Anyway, I have decided on this and Ben's issue that we really are in a stage where we're not that concerned with backwards compatibility where we think there's minimal impact, or that we are making a worthy change. This is because Morph's status in sf is still listed as "Beta." Some projects (e.g. iText) don't give a rat's ass about BC, anyway. :) -Matt ____________________________________________________________________________________ Sucker-punch spam with award-winning protection. Try the free Yahoo! Mail Beta. http://advision.webevents.yahoo.com/mailbeta/features_spam.html |
From: Ben A. <ben...@ac...> - 2007-01-14 19:00:57
|
Ben Alex wrote: > I've attached the patch (described in my last post). It has been working > fine here. Hi guys Any progress on this? I really need this functionality in core. I've been using the patch successfully for a few days now. A further reason we've found for supporting a modified InstantiatingReflector is to retrieve existing objects from a repository that we want to decorate with changes from an input DTO. There are therefore several usage scenarios which benefit from the "Object parameters" additional parameter on the interface method. Cheers Ben |
From: Matt B. <gud...@ya...> - 2007-01-13 15:28:21
|
Responses inline: --- Matt Sgarlata <Mat...@wh...> wrote: > Wow I'm slow getting back to you >< All these > changes look great! I'm > very glad you have SVN access for this stuff :) > Thanks. :) > Here are some minor changes I made: > - ReflectionInfo class, took your change of > !isLowerCase and further > refined it to be isUpperCase. Also applied the > change in multiple > places (you only caught 1 of the 3 places the check > happened) I probably outsmarted myself there; I was thinking of something like set7foo or something but since 7foo wouldn't be a valid property (member) name anyway it really doesn't matter. :) > - NumberToBooleanConverter, added comment indicating > .equals cannot be > used (to prevent someone going in there and messing > it up in the future) > - ObjectToClassConverter, added comment explaining > why > isTransformableImpl was implemented (for > performance) > > Regarding the MultipleDestinationConverter, the > final call in the class > was probably supposed to be > getContainerConverter().convert(destinationClass, > *destinationObjects*, > locale); I went ahead and made this change. This > class was created > because someone was challenging me that my > interfaces only allowed 1 -> > 1 object conversions as opposed to also allowing one > object to be broken > into several smaller object or several smaller > objects to be combined > into 1 larger object. The idea here would be you > had something like, > say, a Person that you wanted to be converted into a > collection of > smaller objects like PoliticalViews, BankAccount, > Cars. Those 3 smaller > objects would have to be returned as some type of > collection, say as a > List or an array of Object[]s. That was what the > final call to > getContainerConverter() was for. Really this is > more of a hypothetical > class to show that this type of thing was possible > to my friend I was > hoping would get involved in the project (didn't > work). I don't > anticipate anyone would actually use this class, and > I probably haven't > even looked at it since the date it was first > written. Perhaps we > should just delete it? > No, I think it has a place. There's some Fowlerism like "Assembly Pattern" or something that this should be an example of... Dozer explicitly mentions it in their manual, so you're probably best off keeping it for competitive reasons. We should just try to document it better and provide examples. Does this mean CombiningCopier was meant as the opposite of MultipleDestinationConverter? > Question: why did you put in clone() calls in the > TimeConverter, if the > source class = destination class? By way of > compmarison, the > IdentityConverter does not attempt to make copies of > source objects and > just returns them unchanged. The tradeoff as I see > it is that clone() > is "safer" but just returning the source unchanged > is faster. Since we > can't universally clone objects (since not all > objects implement that > interface), would it be best to just never do > cloning of source objects? Here are my thoughts: you can't just return the original instance when the source class is Date or Calendar, because both classes are mutable. If they weren't they could just have been included in the IdentityConverter's list of source/dest classes... since they are mutable you want (IMO) to break their existences apart so that they can have individual identity... kind of the very concept of "clone". And I don't see anything wrong with a converter that knows it operates on a finite number of classes, and that all of those classes implement Cloneable (it's highly unlikely that will be retracted in the future), making use of that knowledge. > > Suggestion: how about we rename Int to > MutableInteger, to more > accurately describe what it is for? This would also > preclude confusion > regarding what is returned by the Morph.convertToInt > method. > This is fine with me. It's funny because some of the test cases rely on stuff like commons-lang, which, of course, has a MutableInteger already. Although this Int is probably less encapsulated since I left the value member public for quick/easy use. > FYI: I made some improvements to > MorphPropertyEditor, which I am > actively using in one of my apps to customize > Spring's data binding > behavior (I happen to need some behavior that is not > Morph's default, > specifically related to the TextToNumberConverter) Cool. -Matt B > > Matt > > Matt Benson wrote: > > Matt S (and anyone else who may be watching): > > > > I have been working in the Morph codebase > yesterday > > and today. Highlights of what I've done: > > > > r10 | matt.benson | 2007-01-08 13:38:04 -0600 > (Mon, 08 > > Jan 2007) | 3 lines > > > > Fix/improve date-related test failures by sticking > to > > Calendar instead of Date > > whenever possible. > > > > -Allowed me to establish a baseline of > all-tests-pass. > > > > r11 | matt.benson | 2007-01-08 13:49:02 -0600 > (Mon, 08 > > Jan 2007) | 2 lines > > > > Fix ChainedConverter so that it will work > correctly > > for ExplicitTransformers. > > > > -The original bug I saw that I thought I could > fix. > > > > r17 | matt.benson | 2007-01-08 16:38:16 -0600 > (Mon, 08 > > Jan 2007) | 1 line > > > > make text converter handle byte and char arrays > > > > -Seemed like the right thing to do. > > > > r18 | matt.benson | 2007-01-08 16:48:00 -0600 > (Mon, 08 > > Jan 2007) | 1 line > > > > delegate text to boolean conversion using a > > textconverter, thus gaining any additional source > > classes added to textconverter for free > > > > -followed naturally from the previous change. > > > > r19 | matt.benson | 2007-01-08 16:51:31 -0600 > (Mon, 08 > > Jan 2007) | 1 line > > > > fix broken stack management and add object to > pretty > > text converter test case > > > > -ObjectToPrettyTextConverter had no test case and > > didn't work properly. :( > > > > r29 | matt.benson | 2007-01-08 17:22:06 -0600 > (Mon, 08 > > Jan 2007) | 2 lines > > > > add missing primitives; quicker > isTransformableImpl(); > > eliminate code duplication > > > > -I couldn't think why ObjectToClassConverter > allowed > > all primitives as sources except for boolean and > char, > > so I added them. Since this converter's only > > destination Class is Class, and Class is final, I > > overrode isTransformableImpl to check whether the > > destinationType were Class.class... > > > > r32 | matt.benson | 2007-01-08 17:30:32 -0600 > (Mon, 08 > > Jan 2007) | 1 line > > > > add UnsupportedOperationException to > > CombiningCopier.copyImpl() > > > > -not yet implemented > > > > Additionally I made several changes having to do > with > > eliminating redundant (explicitly or logically) > code, > > reducing method calls, object instantiations, > source > > file size, etc. where I saw possibilities. Some > of > > these could be considered style issues so I hope I > > haven't overstepped any bounds here. > > > > br, > > Matt B > > > > __________________________________________________ > > Do You Yahoo!? > > Tired of spam? Yahoo! Mail has the best spam > protection around > > http://mail.yahoo.com > > > > > ------------------------------------------------------------------------- > > Take Surveys. Earn Cash. Influence the Future of > IT > > Join SourceForge.net's Techsay panel and you'll > get the chance to share your > > opinions on IT & business topics through brief > surveys - and earn cash > > > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > > _______________________________________________ > > morph-developer mailing list > > mor...@li... > > > https://lists.sourceforge.net/lists/listinfo/morph-developer > > > > > > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get > the chance to share your > opinions on IT & business topics through brief > surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > ____________________________________________________________________________________ Any questions? Get answers on any topic at www.Answers.yahoo.com. Try it now. |
From: Matt S. <Mat...@wh...> - 2007-01-13 00:20:48
|
Wow I'm slow getting back to you >< All these changes look great! I'm very glad you have SVN access for this stuff :) Here are some minor changes I made: - ReflectionInfo class, took your change of !isLowerCase and further refined it to be isUpperCase. Also applied the change in multiple places (you only caught 1 of the 3 places the check happened) - NumberToBooleanConverter, added comment indicating .equals cannot be used (to prevent someone going in there and messing it up in the future) - ObjectToClassConverter, added comment explaining why isTransformableImpl was implemented (for performance) Regarding the MultipleDestinationConverter, the final call in the class was probably supposed to be getContainerConverter().convert(destinationClass, *destinationObjects*, locale); I went ahead and made this change. This class was created because someone was challenging me that my interfaces only allowed 1 -> 1 object conversions as opposed to also allowing one object to be broken into several smaller object or several smaller objects to be combined into 1 larger object. The idea here would be you had something like, say, a Person that you wanted to be converted into a collection of smaller objects like PoliticalViews, BankAccount, Cars. Those 3 smaller objects would have to be returned as some type of collection, say as a List or an array of Object[]s. That was what the final call to getContainerConverter() was for. Really this is more of a hypothetical class to show that this type of thing was possible to my friend I was hoping would get involved in the project (didn't work). I don't anticipate anyone would actually use this class, and I probably haven't even looked at it since the date it was first written. Perhaps we should just delete it? Question: why did you put in clone() calls in the TimeConverter, if the source class = destination class? By way of compmarison, the IdentityConverter does not attempt to make copies of source objects and just returns them unchanged. The tradeoff as I see it is that clone() is "safer" but just returning the source unchanged is faster. Since we can't universally clone objects (since not all objects implement that interface), would it be best to just never do cloning of source objects? Suggestion: how about we rename Int to MutableInteger, to more accurately describe what it is for? This would also preclude confusion regarding what is returned by the Morph.convertToInt method. FYI: I made some improvements to MorphPropertyEditor, which I am actively using in one of my apps to customize Spring's data binding behavior (I happen to need some behavior that is not Morph's default, specifically related to the TextToNumberConverter) Matt Matt Benson wrote: > Matt S (and anyone else who may be watching): > > I have been working in the Morph codebase yesterday > and today. Highlights of what I've done: > > r10 | matt.benson | 2007-01-08 13:38:04 -0600 (Mon, 08 > Jan 2007) | 3 lines > > Fix/improve date-related test failures by sticking to > Calendar instead of Date > whenever possible. > > -Allowed me to establish a baseline of all-tests-pass. > > r11 | matt.benson | 2007-01-08 13:49:02 -0600 (Mon, 08 > Jan 2007) | 2 lines > > Fix ChainedConverter so that it will work correctly > for ExplicitTransformers. > > -The original bug I saw that I thought I could fix. > > r17 | matt.benson | 2007-01-08 16:38:16 -0600 (Mon, 08 > Jan 2007) | 1 line > > make text converter handle byte and char arrays > > -Seemed like the right thing to do. > > r18 | matt.benson | 2007-01-08 16:48:00 -0600 (Mon, 08 > Jan 2007) | 1 line > > delegate text to boolean conversion using a > textconverter, thus gaining any additional source > classes added to textconverter for free > > -followed naturally from the previous change. > > r19 | matt.benson | 2007-01-08 16:51:31 -0600 (Mon, 08 > Jan 2007) | 1 line > > fix broken stack management and add object to pretty > text converter test case > > -ObjectToPrettyTextConverter had no test case and > didn't work properly. :( > > r29 | matt.benson | 2007-01-08 17:22:06 -0600 (Mon, 08 > Jan 2007) | 2 lines > > add missing primitives; quicker isTransformableImpl(); > eliminate code duplication > > -I couldn't think why ObjectToClassConverter allowed > all primitives as sources except for boolean and char, > so I added them. Since this converter's only > destination Class is Class, and Class is final, I > overrode isTransformableImpl to check whether the > destinationType were Class.class... > > r32 | matt.benson | 2007-01-08 17:30:32 -0600 (Mon, 08 > Jan 2007) | 1 line > > add UnsupportedOperationException to > CombiningCopier.copyImpl() > > -not yet implemented > > Additionally I made several changes having to do with > eliminating redundant (explicitly or logically) code, > reducing method calls, object instantiations, source > file size, etc. where I saw possibilities. Some of > these could be considered style issues so I hope I > haven't overstepped any bounds here. > > br, > Matt B > > __________________________________________________ > Do You Yahoo!? > Tired of spam? Yahoo! Mail has the best spam protection around > http://mail.yahoo.com > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > > |
From: Ben A. <ben...@ac...> - 2007-01-12 06:29:34
|
I've attached the patch (described in my last post). It has been working fine here. Cheers Ben |
From: Ben A. <ben...@ac...> - 2007-01-12 01:22:56
|
Matt Benson wrote: > Ben, can you provide a little more info on your setup? > I'd love to. Most of the world are developing anemic domain objects, so public no-argument constructors in so-called "domain objects" are everywhere. There's no question as to their convenience, but there is significant momentum behind a shift to domain driven design, which essentially advocates proper object orientation - including both encapsulation and state integrity. As such, people are actually starting to use constructors for their original purpose, being to construct an object and then allow the object's methods to continue to preserve state integrity. In ROO we use constructors typically to represent the mandatory properties of an object, such that the object cannot exist in memory unless those mandatory properties are provided. We limit the provision of mutator methods to only those properties which are not state managed (ie we don't care what they become) or the mutator method itself is capable of ensuring validation. We are using Morph to covert between data transfer objects and domain objects. As such, an input DTO will contain all of the properties necessary to construct a domain object. However, we need to map between the DTO fields and the domain object constructor parameter names. It's quite easy to extract this information, and Spring offers an interface (ParameterNameDiscoverer) for this purpose. I'll describe it further below. In terms of my change request, I would suggest implementation as follows (I've done this on a local copy and it worked well): - Change the existing InstantiatingReflector.newInstance(Class) method to include a second "Object parameters" parameter. - Change the final BaseReflector.newInstance(Class) method to final BaseReflector.newInstance(Class, Object). Delegate through to a new method, BaseReflector.newInstanceImpl(Class, Object). - Change the BaseReflector.newInstanceImpl(Class) to be marked as final and deprecated, noting that subclasses should now use BaseReflector.newInstanceImpl(Class, Object). Marking it as final will of course immediately show up any of the deprecated users of the method as people upgrade Morph. - Add a new BaseReflector.newInstanceImpl(Class, Object) method which by default has the same behavior as the old BaseReflector.newInstanceImpl(Class). - Modify Morph subclasses accordingly to no longer use the BaseReflector.newInstanceImpl(Class) method. Such classes are easy to find, as the superclass method is now marked final. - Modify BaseTransformer.createNewInsanceImpl(Class, Object source) to delegate the source argument through to the InstantiatingReflector method. Realistically, I don't anticipate many end users (ie outside Morph framework itself) would have overridden BaseReflector.newInstanceImpl(Class), simply because there isn't a great deal that you can do with that method signature in the first place. I mean, you can create the required object using its no-argument parameter and return it. If people are doing more exotic things, they'd probably like the flexibility of the new signature format. You know the Morph community better than I do, but I don't think this simple change (adding one parameter to a method signature if they happen to override BaseReflector.newInstanceImpl(Class)) is going to be necessary for many people. As you may have guessed, I don't believe that an additional method on the InstantiatingReflector interface is ideal. I did suggest it, as a way of avoiding backward compatibility issues, but the legacy of the decision will remain far longer than the deprecated final BaseReflector.newInstanceImpl(Class) needs to be retained. You'd also need users of InstantiatingReflector to decide which method to invoke, and/or maintain separate delegation approaches in common superclasses like BaseReflector. It just doesn't feel as clean as marking a method final and deprecated, and being done with a nice clean change. To explore Matt B's suggestion as to an automatic algorithm to construct the object if it doesn't offer a no-argument constructor, what we currently do is look for the shortest public constructor on the destination class and use it. If it's no-argument, that's easy. If it accepts arguments, obtain the parameter names from the compiled source code's debug information via Spring's ParameterNameDiscoverer and then look for accessor methods or public fields on the source object that match those names. If found, you have an argument to present as that parameter. If not found, configurable behaviour should be offered such as throwing an exception, trying the next public constructor, or using null (or a suitable default if a primitive). Such behaviour would appear quite a comprehensive approach for something like BaseReflector.newInstanceImpl(Class, Object), although I am not necessarily advocating its inclusion. An issue to contemplate is the need to include an ASM dependency for the necessary parameter name visitor support, and possibly Spring if you'd like ParameterNameDiscoverer and a usable implementation. There's something to be said for keeping Morph lightweight and free of additional dependencies, leaving more exotic users to add those JARs and override BaseReflector (I am happy to do this). Equally, this logic might be positive to include, instead using reflection to obtain the method from ParameterNameDiscoverer if it's detected in the classpath (thus avoiding a compile-time dependency but still offering more sophisticated construction support for the many people who have Spring in their classpath). If someone can make a decision on the approach, I am very happy to implement it and provide the patch (I can also provide what I've already done, as described above). Cheers Ben |
From: Matt B. <gud...@ya...> - 2007-01-11 20:50:28
|
--- Matt Sgarlata <Mat...@wh...> wrote: > Matt Benson wrote: > > IMO a basic implementation: > > > > look first for a single-arg constructor whose > argument > > matches "parameter". Failing that, if "parameter" > is > > an array, look for a multi-arg constructor whose > > arguments all match the elements of "parameter". > > After these approaches fail, I wouldn't do any > more by > > default, but simply fall back to newInstance(). > I've > > written code that does this stuff before, > actually. > > > > The only thing about all this is it sounds pretty > much > > like a Converter implementation; the line between > > Reflectors and Converters becomes blurry. :| > > > > -Matt > Yeah, this is definitely not the recommended way to > do this stuff. This > would be a great place to quote one of Rod Johnson's > books or the Spring > manual, but I'm too lazy to find a good quote that > goes over why you > should just use default no-argument constructors. > The support here is > IMO for APIs over which the user has no control. If > the user does have > control over the API and they are using constructors > with arguments, > well, they deserve the mess that they have brought > on themselves ;) > > Matt > Hard to say about your invocation of Rod. I just read the pro-con listing for property vs. constructor injection in "Expert One-on-One J2EE Development without EJB" and it agrees with what you've said, but I think interface21's views could be evolving on the subject... Ben is one of them, after all, and he's the requestor here. I know that Keith Donald was pushing for more constructors and fewer setters in Spring Web Flow, and I think the constructor parameter name discovery thing Ben mentioned might have originated with some of the AOP stuff, possibly brought in by Adrian Colyer (but that's complete guesswork on my part). Anyway, I only went into all that to play devil's advocate, as I will tend to do. I am in actuality undecided as yet what the best solution is here. Ben, can you provide a little more info on your setup? -Matt B > > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get > the chance to share your > opinions on IT & business topics through brief > surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > ____________________________________________________________________________________ Have a burning question? Go to www.Answers.yahoo.com and get answers from real people who know. |
From: Matt S. <Mat...@wh...> - 2007-01-11 20:33:23
|
Matt Benson wrote: > IMO a basic implementation: > > look first for a single-arg constructor whose argument > matches "parameter". Failing that, if "parameter" is > an array, look for a multi-arg constructor whose > arguments all match the elements of "parameter". > After these approaches fail, I wouldn't do any more by > default, but simply fall back to newInstance(). I've > written code that does this stuff before, actually. > > The only thing about all this is it sounds pretty much > like a Converter implementation; the line between > Reflectors and Converters becomes blurry. :| > > -Matt Yeah, this is definitely not the recommended way to do this stuff. This would be a great place to quote one of Rod Johnson's books or the Spring manual, but I'm too lazy to find a good quote that goes over why you should just use default no-argument constructors. The support here is IMO for APIs over which the user has no control. If the user does have control over the API and they are using constructors with arguments, well, they deserve the mess that they have brought on themselves ;) Matt |
From: Matt B. <gud...@ya...> - 2007-01-11 20:27:35
|
IMO a basic implementation: look first for a single-arg constructor whose argument matches "parameter". Failing that, if "parameter" is an array, look for a multi-arg constructor whose arguments all match the elements of "parameter". After these approaches fail, I wouldn't do any more by default, but simply fall back to newInstance(). I've written code that does this stuff before, actually. The only thing about all this is it sounds pretty much like a Converter implementation; the line between Reflectors and Converters becomes blurry. :| -Matt --- Matt Sgarlata <Mat...@wh...> wrote: > That's certainly a possibility, but what algorithm > would be used to try > to guess which parameters go where? Would guesses > be based on the type > of the "parameters" object, or would be reflection > be used to try to > "extract" the parameters, etc. This could > potentially be very complex > and still not meet a user's requirements. How often > do we encounter > objects which do not have a no-arg constructor, > especially with Spring > having been around for so long? I know I myself > would probably never > use this feature. > > That said, if you want to spend some time working on > a solution, it's > your free time not mine :) > > Matt > > Matt Benson wrote: > > Thinking more on this, it seems more correct that > a > > basic implementation of newInstance(Object > parameters) > > would look for constructors matching the > parameters, > > and failing to find any would fall back to the > > no-parameter version. This would probably be MORE > > compatible with any existing > InstantiatingReflector > > implementation as well. > > > > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get > the chance to share your > opinions on IT & business topics through brief > surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > ____________________________________________________________________________________ Cheap talk? Check out Yahoo! Messenger's low PC-to-Phone call rates. http://voice.yahoo.com |
From: Matt S. <Mat...@wh...> - 2007-01-11 19:51:43
|
That's certainly a possibility, but what algorithm would be used to try to guess which parameters go where? Would guesses be based on the type of the "parameters" object, or would be reflection be used to try to "extract" the parameters, etc. This could potentially be very complex and still not meet a user's requirements. How often do we encounter objects which do not have a no-arg constructor, especially with Spring having been around for so long? I know I myself would probably never use this feature. That said, if you want to spend some time working on a solution, it's your free time not mine :) Matt Matt Benson wrote: > Thinking more on this, it seems more correct that a > basic implementation of newInstance(Object parameters) > would look for constructors matching the parameters, > and failing to find any would fall back to the > no-parameter version. This would probably be MORE > compatible with any existing InstantiatingReflector > implementation as well. > |
From: Matt B. <gud...@ya...> - 2007-01-11 18:56:46
|
Thinking more on this, it seems more correct that a basic implementation of newInstance(Object parameters) would look for constructors matching the parameters, and failing to find any would fall back to the no-parameter version. This would probably be MORE compatible with any existing InstantiatingReflector implementation as well. -Matt P.S. Sorry about the bleeding ocular cavity problem. ;) --- Matt Sgarlata <Mat...@wh...> wrote: > That sounds like a good approach Matt B. That way, > if someone has a > reflector that extends from BaseReflector, it will > still work with the > new version of Morph despite the interface change (I > think). Actually > to be really technical, BaseReflector.newInstance is > final, so it's safe > to just change that to match the new signature. > Then > newInstanceImpl(Class) can call > newInstanceImpl(Class, Object) > > BTW, I'm still trying to catch up to all the changes > you made to Morph > this week. I haven't been able to finish, but so > far they look good. I > do see you love the ? : operator ;) I'm fine with > using it extensively, > but I did run into 1 or 2 places that made my eyes > bleed because I > couldn't figure out what was going on. More to come > later... > > Matt > > Matt Benson wrote: > > Matt: I was curious what your take on this would > be. > > I was actually about to answer Ben myself before I > saw > > that you just had. Anyway, even taking the > approach > > of modifying the existing interface, do(n't) you > think > > newInstance(Class clazz, Object parameters) should > be > > a new method entirely, and that BaseReflector can > just > > pass null parameters from the old method to the > new > > method? > > > > -Matt B > > > > --- Matt Sgarlata > > <Mat...@wh...> wrote: > > > > > >> Hi Ben - at first I was quite uncomfortable with > the > >> idea of adding a > >> new parameter to the newInstance method, if only > >> because it takes a very > >> simple method and makes it more complex.. > However, > >> after thinking about > >> it I see that we don't really have a choice. If > you > >> have an object in > >> some external API over which you have no control > >> like this > >> > >> public class Foo { > >> public Foo(int requiredConstructorParam) { } > >> private Foo() { } > >> } > >> > >> Then there is no way to create the object without > >> passing in the > >> requiredConstructorParam (e.g., java.lang.Integer > >> works like this). So, > >> when the object is created you really do need > more > >> information than just > >> the class of the object to be created. One minor > >> thing is that > >> reflectors don't necessarily have anything to do > >> with transformations > >> (though that is the way they will generally be > >> used). So I would change > >> the name of the new parameter you introduced to > be > >> "parameters", which > >> indicates the object is one or more parameters > used > >> in the object > >> creation. In BaseTransformer, we would pass in > the > >> source object. In > >> some other use case, perhaps parameters would be > a > >> Map with name/value > >> keys for the different fields to be initialized > in > >> the new instance. > >> What was required of the "parameters" object > would > >> be dictated by the > >> particular Reflector implementation. > >> > >> public Object newInstance(Class clazz, Object > >> parameters) throws > >> ReflectionException; > >> > >> I'm inclined to just add the parameter to the > base > >> interface, despite > >> the potential for some compatibility issues. > >> Logically when you create > >> an instance of an object there's the potential > for > >> you to need to know > >> more information than just the class, and I don't > >> think it makes sense > >> to support 2 different interfaces when 1 will > >> suffice. > >> > >> Matt > >> > >> Ben Alex wrote: > >> > >>> Hi > >>> > >>> We have a requirement to instantiate objects > using > >>> > >> complex constructors > >> > >>> (not simply no-argument constructors). > Essentially > >>> > >> we will use parameter > >> > >>> name discovery to retrieve the request parameter > >>> > >> names from the > >> > >>> constructor, then source the properties from the > >>> > >> input object. We do > >> > >>> this with Dozer quite successfully. > >>> > >>> InstantiatingReflector appears the appropriate > >>> > >> Morph interface: > >> > >>> public Object newInstance(Class clazz) throws > >>> > >> ReflectionException; > >> > >>> This is invoked by the BaseTransformer method: > >>> > >>> protected Object createNewInstanceImpl(Class > >>> > >> destinationClass, > >> > >>> Object source) > throws > >>> > >> Exception; > >> > >>> I would like to request a change so that > >>> > >> InstantiatingReflector is > >> > >>> provided the source object, which we need in > order > >>> > >> to perform the > >> > >>> desired destination object construction. ie: > >>> > >>> public Object newInstance(Class clazz, Object > >>> > >> source) throws > >> > >>> ReflectionException; > >>> > >>> I don't see this as a major problem, given that > >>> > >> existing > >> > >>> InstantiatingReflector implementations can > simply > >>> > >> ignore the additional > >> > >>> parameter if they don't wish to use it. > >>> > >>> Alternately, if backward compatibility were an > >>> > >> issue, could we have a > >> > >>> new interface (InstantiatingSourceReflector?) > >>> > >> which provided the > >> > >>> interface, and have this new implementation > extend > >>> InstantiatingReflector. Then BaseTransformer > would > >>> > >> detect the type of > >> > >>> instantiating reflector injected and invoke > >>> > >> accordingly. > >> > >>> I realise we could simply override the > >>> > >> BaseTransformer method, but then > >> > >>> we force concrete inheritance to be used when a > >>> > >> strategy pattern already > >> > >>> exists and makes more sense. We just need the > >>> > >> strategy to present the > >> > >>> additional parameter. > >>> > >>> I'm happy to make this change and provide a > patch, > >>> > >> but I wanted to check > >> > >>> which approach (or some other) that people > >>> > >> preferred. > >> > >>> Thanks > >>> Ben > >>> > >>> > >>> > > > ------------------------------------------------------------------------- > > > >>> Take Surveys. Earn Cash. Influence the Future of > >>> > >> IT > >> > >>> Join SourceForge.net's Techsay panel and you'll > >>> > >> get the chance to share your > >> > >>> opinions on IT & business topics through brief > >>> > >> surveys - and earn cash > >> > > > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > > > >>> _______________________________________________ > >>> morph-developer mailing list > >>> mor...@li... > >>> > >>> > > > https://lists.sourceforge.net/lists/listinfo/morph-developer > > > >>> > >>> > >> > >> > > > ------------------------------------------------------------------------- > > > >> Take Surveys. Earn Cash. Influence the Future of > IT > >> Join SourceForge.net's Techsay panel and you'll > get > >> the chance to share your > >> opinions on IT & business topics through brief > >> surveys - and earn cash > >> > >> > > > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > > > >> _______________________________________________ > >> morph-developer mailing list > >> mor...@li... > >> > >> > > > https://lists.sourceforge.net/lists/listinfo/morph-developer > > > > > > > > __________________________________________________ > > Do You Yahoo!? > > Tired of spam? Yahoo! Mail has the best spam > protection around > > http://mail.yahoo.com > > > > > ------------------------------------------------------------------------- > > Take Surveys. Earn Cash. Influence the Future of > IT > > Join SourceForge.net's Techsay panel and you'll > get the chance to share your > > opinions on IT & business topics through brief > surveys - and earn cash > > > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > > _______________________________________________ > > morph-developer mailing list > > mor...@li... > > > https://lists.sourceforge.net/lists/listinfo/morph-developer > > > > > > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get > the chance to share your > opinions on IT & business topics through brief > surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV> _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > ____________________________________________________________________________________ Do you Yahoo!? Everyone is raving about the all-new Yahoo! Mail beta. http://new.mail.yahoo.com |
From: Matt S. <Mat...@wh...> - 2007-01-11 17:29:32
|
That sounds like a good approach Matt B. That way, if someone has a reflector that extends from BaseReflector, it will still work with the new version of Morph despite the interface change (I think). Actually to be really technical, BaseReflector.newInstance is final, so it's safe to just change that to match the new signature. Then newInstanceImpl(Class) can call newInstanceImpl(Class, Object) BTW, I'm still trying to catch up to all the changes you made to Morph this week. I haven't been able to finish, but so far they look good. I do see you love the ? : operator ;) I'm fine with using it extensively, but I did run into 1 or 2 places that made my eyes bleed because I couldn't figure out what was going on. More to come later... Matt Matt Benson wrote: > Matt: I was curious what your take on this would be. > I was actually about to answer Ben myself before I saw > that you just had. Anyway, even taking the approach > of modifying the existing interface, do(n't) you think > newInstance(Class clazz, Object parameters) should be > a new method entirely, and that BaseReflector can just > pass null parameters from the old method to the new > method? > > -Matt B > > --- Matt Sgarlata > <Mat...@wh...> wrote: > > >> Hi Ben - at first I was quite uncomfortable with the >> idea of adding a >> new parameter to the newInstance method, if only >> because it takes a very >> simple method and makes it more complex.. However, >> after thinking about >> it I see that we don't really have a choice. If you >> have an object in >> some external API over which you have no control >> like this >> >> public class Foo { >> public Foo(int requiredConstructorParam) { } >> private Foo() { } >> } >> >> Then there is no way to create the object without >> passing in the >> requiredConstructorParam (e.g., java.lang.Integer >> works like this). So, >> when the object is created you really do need more >> information than just >> the class of the object to be created. One minor >> thing is that >> reflectors don't necessarily have anything to do >> with transformations >> (though that is the way they will generally be >> used). So I would change >> the name of the new parameter you introduced to be >> "parameters", which >> indicates the object is one or more parameters used >> in the object >> creation. In BaseTransformer, we would pass in the >> source object. In >> some other use case, perhaps parameters would be a >> Map with name/value >> keys for the different fields to be initialized in >> the new instance. >> What was required of the "parameters" object would >> be dictated by the >> particular Reflector implementation. >> >> public Object newInstance(Class clazz, Object >> parameters) throws >> ReflectionException; >> >> I'm inclined to just add the parameter to the base >> interface, despite >> the potential for some compatibility issues. >> Logically when you create >> an instance of an object there's the potential for >> you to need to know >> more information than just the class, and I don't >> think it makes sense >> to support 2 different interfaces when 1 will >> suffice. >> >> Matt >> >> Ben Alex wrote: >> >>> Hi >>> >>> We have a requirement to instantiate objects using >>> >> complex constructors >> >>> (not simply no-argument constructors). Essentially >>> >> we will use parameter >> >>> name discovery to retrieve the request parameter >>> >> names from the >> >>> constructor, then source the properties from the >>> >> input object. We do >> >>> this with Dozer quite successfully. >>> >>> InstantiatingReflector appears the appropriate >>> >> Morph interface: >> >>> public Object newInstance(Class clazz) throws >>> >> ReflectionException; >> >>> This is invoked by the BaseTransformer method: >>> >>> protected Object createNewInstanceImpl(Class >>> >> destinationClass, >> >>> Object source) throws >>> >> Exception; >> >>> I would like to request a change so that >>> >> InstantiatingReflector is >> >>> provided the source object, which we need in order >>> >> to perform the >> >>> desired destination object construction. ie: >>> >>> public Object newInstance(Class clazz, Object >>> >> source) throws >> >>> ReflectionException; >>> >>> I don't see this as a major problem, given that >>> >> existing >> >>> InstantiatingReflector implementations can simply >>> >> ignore the additional >> >>> parameter if they don't wish to use it. >>> >>> Alternately, if backward compatibility were an >>> >> issue, could we have a >> >>> new interface (InstantiatingSourceReflector?) >>> >> which provided the >> >>> interface, and have this new implementation extend >>> InstantiatingReflector. Then BaseTransformer would >>> >> detect the type of >> >>> instantiating reflector injected and invoke >>> >> accordingly. >> >>> I realise we could simply override the >>> >> BaseTransformer method, but then >> >>> we force concrete inheritance to be used when a >>> >> strategy pattern already >> >>> exists and makes more sense. We just need the >>> >> strategy to present the >> >>> additional parameter. >>> >>> I'm happy to make this change and provide a patch, >>> >> but I wanted to check >> >>> which approach (or some other) that people >>> >> preferred. >> >>> Thanks >>> Ben >>> >>> >>> > ------------------------------------------------------------------------- > >>> Take Surveys. Earn Cash. Influence the Future of >>> >> IT >> >>> Join SourceForge.net's Techsay panel and you'll >>> >> get the chance to share your >> >>> opinions on IT & business topics through brief >>> >> surveys - and earn cash >> > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > >>> _______________________________________________ >>> morph-developer mailing list >>> mor...@li... >>> >>> > https://lists.sourceforge.net/lists/listinfo/morph-developer > >>> >>> >> >> > ------------------------------------------------------------------------- > >> Take Surveys. Earn Cash. Influence the Future of IT >> Join SourceForge.net's Techsay panel and you'll get >> the chance to share your >> opinions on IT & business topics through brief >> surveys - and earn cash >> >> > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > >> _______________________________________________ >> morph-developer mailing list >> mor...@li... >> >> > https://lists.sourceforge.net/lists/listinfo/morph-developer > > > > __________________________________________________ > Do You Yahoo!? > Tired of spam? Yahoo! Mail has the best spam protection around > http://mail.yahoo.com > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > > |
From: Matt B. <gud...@ya...> - 2007-01-11 17:15:25
|
Matt: I was curious what your take on this would be. I was actually about to answer Ben myself before I saw that you just had. Anyway, even taking the approach of modifying the existing interface, do(n't) you think newInstance(Class clazz, Object parameters) should be a new method entirely, and that BaseReflector can just pass null parameters from the old method to the new method? -Matt B --- Matt Sgarlata <Mat...@wh...> wrote: > Hi Ben - at first I was quite uncomfortable with the > idea of adding a > new parameter to the newInstance method, if only > because it takes a very > simple method and makes it more complex.. However, > after thinking about > it I see that we don't really have a choice. If you > have an object in > some external API over which you have no control > like this > > public class Foo { > public Foo(int requiredConstructorParam) { } > private Foo() { } > } > > Then there is no way to create the object without > passing in the > requiredConstructorParam (e.g., java.lang.Integer > works like this). So, > when the object is created you really do need more > information than just > the class of the object to be created. One minor > thing is that > reflectors don't necessarily have anything to do > with transformations > (though that is the way they will generally be > used). So I would change > the name of the new parameter you introduced to be > "parameters", which > indicates the object is one or more parameters used > in the object > creation. In BaseTransformer, we would pass in the > source object. In > some other use case, perhaps parameters would be a > Map with name/value > keys for the different fields to be initialized in > the new instance. > What was required of the "parameters" object would > be dictated by the > particular Reflector implementation. > > public Object newInstance(Class clazz, Object > parameters) throws > ReflectionException; > > I'm inclined to just add the parameter to the base > interface, despite > the potential for some compatibility issues. > Logically when you create > an instance of an object there's the potential for > you to need to know > more information than just the class, and I don't > think it makes sense > to support 2 different interfaces when 1 will > suffice. > > Matt > > Ben Alex wrote: > > Hi > > > > We have a requirement to instantiate objects using > complex constructors > > (not simply no-argument constructors). Essentially > we will use parameter > > name discovery to retrieve the request parameter > names from the > > constructor, then source the properties from the > input object. We do > > this with Dozer quite successfully. > > > > InstantiatingReflector appears the appropriate > Morph interface: > > > > public Object newInstance(Class clazz) throws > ReflectionException; > > > > This is invoked by the BaseTransformer method: > > > > protected Object createNewInstanceImpl(Class > destinationClass, > > Object source) throws > Exception; > > > > I would like to request a change so that > InstantiatingReflector is > > provided the source object, which we need in order > to perform the > > desired destination object construction. ie: > > > > public Object newInstance(Class clazz, Object > source) throws > > ReflectionException; > > > > I don't see this as a major problem, given that > existing > > InstantiatingReflector implementations can simply > ignore the additional > > parameter if they don't wish to use it. > > > > Alternately, if backward compatibility were an > issue, could we have a > > new interface (InstantiatingSourceReflector?) > which provided the > > interface, and have this new implementation extend > > InstantiatingReflector. Then BaseTransformer would > detect the type of > > instantiating reflector injected and invoke > accordingly. > > > > I realise we could simply override the > BaseTransformer method, but then > > we force concrete inheritance to be used when a > strategy pattern already > > exists and makes more sense. We just need the > strategy to present the > > additional parameter. > > > > I'm happy to make this change and provide a patch, > but I wanted to check > > which approach (or some other) that people > preferred. > > > > Thanks > > Ben > > > > > ------------------------------------------------------------------------- > > Take Surveys. Earn Cash. Influence the Future of > IT > > Join SourceForge.net's Techsay panel and you'll > get the chance to share your > > opinions on IT & business topics through brief > surveys - and earn cash > > > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > > _______________________________________________ > > morph-developer mailing list > > mor...@li... > > > https://lists.sourceforge.net/lists/listinfo/morph-developer > > > > > > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get > the chance to share your > opinions on IT & business topics through brief > surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com |
From: Matt S. <Mat...@wh...> - 2007-01-11 17:00:54
|
Hi Ben - at first I was quite uncomfortable with the idea of adding a new parameter to the newInstance method, if only because it takes a very simple method and makes it more complex.. However, after thinking about it I see that we don't really have a choice. If you have an object in some external API over which you have no control like this public class Foo { public Foo(int requiredConstructorParam) { } private Foo() { } } Then there is no way to create the object without passing in the requiredConstructorParam (e.g., java.lang.Integer works like this). So, when the object is created you really do need more information than just the class of the object to be created. One minor thing is that reflectors don't necessarily have anything to do with transformations (though that is the way they will generally be used). So I would change the name of the new parameter you introduced to be "parameters", which indicates the object is one or more parameters used in the object creation. In BaseTransformer, we would pass in the source object. In some other use case, perhaps parameters would be a Map with name/value keys for the different fields to be initialized in the new instance. What was required of the "parameters" object would be dictated by the particular Reflector implementation. public Object newInstance(Class clazz, Object parameters) throws ReflectionException; I'm inclined to just add the parameter to the base interface, despite the potential for some compatibility issues. Logically when you create an instance of an object there's the potential for you to need to know more information than just the class, and I don't think it makes sense to support 2 different interfaces when 1 will suffice. Matt Ben Alex wrote: > Hi > > We have a requirement to instantiate objects using complex constructors > (not simply no-argument constructors). Essentially we will use parameter > name discovery to retrieve the request parameter names from the > constructor, then source the properties from the input object. We do > this with Dozer quite successfully. > > InstantiatingReflector appears the appropriate Morph interface: > > public Object newInstance(Class clazz) throws ReflectionException; > > This is invoked by the BaseTransformer method: > > protected Object createNewInstanceImpl(Class destinationClass, > Object source) throws Exception; > > I would like to request a change so that InstantiatingReflector is > provided the source object, which we need in order to perform the > desired destination object construction. ie: > > public Object newInstance(Class clazz, Object source) throws > ReflectionException; > > I don't see this as a major problem, given that existing > InstantiatingReflector implementations can simply ignore the additional > parameter if they don't wish to use it. > > Alternately, if backward compatibility were an issue, could we have a > new interface (InstantiatingSourceReflector?) which provided the > interface, and have this new implementation extend > InstantiatingReflector. Then BaseTransformer would detect the type of > instantiating reflector injected and invoke accordingly. > > I realise we could simply override the BaseTransformer method, but then > we force concrete inheritance to be used when a strategy pattern already > exists and makes more sense. We just need the strategy to present the > additional parameter. > > I'm happy to make this change and provide a patch, but I wanted to check > which approach (or some other) that people preferred. > > Thanks > Ben > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > morph-developer mailing list > mor...@li... > https://lists.sourceforge.net/lists/listinfo/morph-developer > > |