Hi David L, The as() method (at least in its current incantation) say something about how to treat the source object - the thing you are converting from. So in your example myDtoWithMethods = converter.convert(map).as(PlainDTO.class).to(DtoWithMethods.class)
it would try to treat the source map as a PlainDTO - which obviously will fail. I guess what you're looking for is a way to say: 'create a target object from this class, but treat it as if it was that class', so maybe something like this?: myDtoWithMethods = converter.convert(map).to(PlainDTO.class).in(DtoWithMethods.class) This is not yet implemented, it's just a suggestion. WDYT? Cheers, David On 18 October 2016 at 11:27, David Leangen <o...@leangen.net> wrote: > > Hi David B., > > Thanks for this suggestion. That would indeed work nicely. As you say, it > requires an extra class, but at least there is very little duplication, at > least converting TO something. > > Converting TO: > > > Map m = converter.convert(myDtoWithMethods).as(PlainDTO. > class).to(Map.class) > > When converting FROM something, would this work? > > myDtoWithMethods = converter.convert(map).as(PlainDTO.class).to( > DtoWithMethods.class) > > If so, then I think this would work just fine! > > > Cheers, > =David > > > > On Oct 18, 2016, at 6:13 PM, David Bosschaert < > david.bosscha...@gmail.com> wrote: > > > > Hi David L, > > > > Recently I added the 'as()' method to the converter, which is really > meant > > to disambiguate source objects. Let's say you have an object that is > both a > > JavaBean as well as implementing an interface. The Converter spec will > > specify some 'priority' rules for this, but they may not always be what > you > > want. The as() method can be used to treat the source object in a > > particular way. > > > > For example, let's say your MyClass extends MyBean implements Intf1 > > Let's say you want to force the converter to look at an instance of > MyClass > > as Intf1. > > > > You could then do > > converter.convert(myobj).as(Intf1.class).to(Map.class) > > > > Would it help to use this for the DTO+methods as well? > > You might have: > > > > Class PlainDto { > > public String foo; > > } > > > > Class DtoWithMethods extends PlainDto { > > public int someMethod() {} > > } > > > > And then maybe use these via: > > converter.convert(myDtoWithMethods).as(PlainDTO.class).to(Map.class) > > ? > > > > It would require a separate class that follows the pure DTO rules... > > > > Cheers, > > > > David > > > > > > On 18 October 2016 at 09:49, David Leangen <o...@leangen.net> wrote: > > > >> > >> Hi David B., > >> > >> Thanks. I think you’re right, the spec is quite clear. > >> > >> If I wanted to treat any class like a DTO (ignore the methods and use > only > >> the public fields — just like before the recent changes made to the code > >> base), can you think of any way? > >> > >> Perhaps having “strict” mode to follow the spec to the letter, and a > less > >> strict mode for people like me? > >> > >> > >> wdyt? > >> > >> Cheers, > >> =David > >> > >> > >>> On Oct 18, 2016, at 5:45 PM, David Bosschaert < > >> david.bosscha...@gmail.com> wrote: > >>> > >>> Hi all, > >>> > >>> The OSGi spec for DTOs is pretty clear. Section 57.2 of the R6 Core > spec > >>> states: > >>> > >>> "Data Transfer Objects are public classes with no methods, other than > the > >>> compiler supplied default > >>> constructor" > >>> > >>> Therefore I would be reluctant to use a different definition for the > >>> Converter. > >>> > >>> OTOH I think that there are a couple of options if you like to have > 'DTOs > >>> with behaviour': > >>> * you could use JavaBeans. The getters/setters are understood by the > the > >>> converter and will result in similar behaviour, but the beans can have > >>> other methods too. > >>> * registry your own converter rules for these classes. > >>> > >>> Cheers, > >>> > >>> David > >>> > >>> On 16 October 2016 at 04:18, David Jencks <david_jen...@yahoo.com. > >> invalid> > >>> wrote: > >>> > >>>> Hi David L, > >>>> > >>>> I imagine the “extra step” and “redirection” are the need to create > both > >>>> the SomeDTO and the SomeImpl? > >>>> > >>>> Thinking about this a bit more I’m reminded that sometimes I end up > >>>> thinking that putting that first “this” parameter back into every > method > >>>> that C++ took out might be a good idea :-) > >>>> > >>>> I started down this rabbit hole by thinking, what if we think of DTOs > as > >>>> primitive data types, like int or long, as much as possible. > >>>> > >>>> For your “business method” example, a static method > >>>> > >>>> class SomeHelper { > >>>> public static String calculateFooBar(SomeDTO data) {return data.foo + > >>>> “:” + data.bar;} > >>>> } > >>>> > >>>> makes perhaps more sense than the SomeImpl I proposed before. But if > >> you > >>>> want to do something more complicated, a builder to hold state > (outside > >> the > >>>> DTO, presumably) can make sense: > >>>> > >>>> class SomeBuilder { > >>>> String foo; > >>>> String bar; > >>>> SomeBuilder(SomeDTO data) {foo = data.foo;bar = data.bar;} > >>>> public void append(SomeDTO moreData) { > >>>> data.foo = data.foo + ”,” + moreData.foo; > >>>> data.bar = data.bar + “,” + moreData.bar; > >>>> } > >>>> > >>>> public String calculateFooBar() {return foo + “:” + bar;} > >>>> } > >>>> > >>>> So I wonder what you end up with if you have > >>>> -DTOs > >>>> -a “Helper” class with only static methods taking one or more DTOs > >>>> -a bunch of “builders” that hold state from one or more DTOs during > >>>> multi-step calculations. > >>>> > >>>> I suppose there also needs to be some code to call some of these > >>>> methods/builders, but I think you need that anyway. > >>>> > >>>> thanks > >>>> david jencks > >>>> > >>>> > >>>> > >>>> > >>>>> On Oct 15, 2016, at 5:28 PM, David Leangen <o...@leangen.net> wrote: > >>>>> > >>>>> > >>>>> Hi David J., > >>>>> > >>>>> That is an interesting perspective. > >>>>> > >>>>> Also based on the ideas proposed by Peter, and after a bit of > >>>> experimentation, these are my thoughts: > >>>>> > >>>>> * Java object encapsulation “works", but only if we assume that there > >> is > >>>>> no such thing as reflection. Since an object can be introspected, > it > >>>> means > >>>>> that there is no “complete” encapsulation, only “weak” > >> encapsulation. > >>>>> > >>>>> —> True. Important if thinking about security, maybe, but perhaps > >>>> not > >>>>> very convincing to me to change my thinking. > >>>>> > >>>>> * DTOs are not real “Value Objects” because normally a VO should be > >>>> immutable. > >>>>> However, if all we make are copies, and both the producer and > >>>> consumer understand > >>>>> that it is a copy being shipped, then in the end, I cannot see a > >>>> problem. It will cause me > >>>>> to change some habits, but I don’t see a problem. > >>>>> > >>>>> * Java8 and its “functional” flavour have really started to interest > >> me. > >>>>> > >>>>> > >>>>> Based mostly on the last two thoughts, I have tried using the > pattern I > >>>> wrote in my earlier post. In essence: > >>>>> > >>>>> * API interface - determines the contract with the rest of the world > >>>>> * DTO - for transmitting and serializing (essential for a working > >> system) > >>>>> * Implementation object - usually Value Objects, but sometimes > Entities > >>>>> > >>>>> By following most of the DTO rules, which generally means (1) make > >>>> serialisable data public, (2) provide a no-arg public constructor, and > >> (3) > >>>> have a tree-like structure that only contains other “DTO-type” > objects, > >> the > >>>> DTO can be combined with the implementation. > >>>>> > >>>>> This completely eliminates an extra step. > >>>>> > >>>>> No longer required: serialized data —> DTO —> domain object > >>>>> > >>>>> New method: serialized data —> DTO (==domain object) > >>>>> > >>>>> I have even started to make my “simple” DTOs (i.e. pure VOs with > little > >>>> or no behaviour) part of the API instead of the impl. > >>>>> > >>>>> I have been very pleased with the results so far. However, if we > don’t > >>>> provide the possibility to relax the rules on the DTOs a bit, this > will > >> no > >>>> longer be possible. I would be really sad to not be able to use this > >>>> pattern, unless of course somebody has come up with a better / > alternate > >>>> solution. > >>>>> > >>>>> > >>>>> What you propose below seems like it would encapsulate well, but it > >>>> seems to me that the extra step of redirection would cause duplicate > >> work. > >>>> No? > >>>>> > >>>>> > >>>>> Cheers, > >>>>> =David > >>>>> > >>>>> > >>>>>> On Oct 16, 2016, at 1:10 AM, David Jencks <david_jen...@yahoo.com. > >> INVALID> > >>>> wrote: > >>>>>> > >>>>>> A while ago Peter said something about DTOs violating data hiding or > >>>> encapsulation and I decided that if you think of the DTO as a > primitive > >>>> data type they don’t. Following this line of thinking (which I have > >> not > >>>> been able to try out in practice, just as thought experiments) you’d > >> have > >>>>>> > >>>>>> public class SomeDTO extends DTO { > >>>>>> public String foo; > >>>>>> public String bar; > >>>>>> } > >>>>>> > >>>>>> public interface SomeInterface { > >>>>>> SomeDTO data(); //I’m not sure this is needed > >>>>>> String calculateFooBar(); > >>>>>> } > >>>>>> > >>>>>> public class SomeImpl { > >>>>>> final SomeDTO data; > >>>>>> public SomeImpl(SomeDTO data) {this.data = data;} > >>>>>> public SomeDTO data() {return data;} > >>>>>> public String calculateFooBar() {return data.foo + “:” + data.bar;} > >>>>>> } > >>>>>> > >>>>>> I’m curious how this would work out in an actual situation, > especially > >>>> in knowing fi the “data()” accessor is needed. I’d hope it would only > >> be > >>>> needed for serialization purposes. > >>>>>> > >>>>>> thanks > >>>>>> david jencks > >>>>>> > >>>>>>> On Oct 14, 2016, at 9:52 PM, David Leangen <apa...@leangen.net> > >> wrote: > >>>>>>> > >>>>>>> > >>>>>>> Hi! > >>>>>>> > >>>>>>> I only noticed now that according to the RFC, DTOs cannot contain > >>>> methods. I can understand why this is so, and I do not object. > >>>>>>> > >>>>>>> However, I have found a very practical design pattern whereby I use > >>>> classes that act both as DTOs and domain value objects. In effect, > this > >>>> means that they are DTOs with methods. I am willing to pay the price > of > >>>> having “bloated” DTOs for this convenience. > >>>>>>> > >>>>>>> > >>>>>>> Would there be any way to allow configuration to permit this? > >>>>>>> > >>>>>>> If that is out of the question then any suggestions as to what I > >> could > >>>> do so as to not have to have “duplicate” classes (DTOs and domain > VOs)? > >>>>>>> > >>>>>>> > >>>>>>> Example: > >>>>>>> > >>>>>>> Domain object API > >>>>>>> > >>>>>>> public interface SomeObject { > >>>>>>> String foo(); > >>>>>>> String bar(); > >>>>>>> String calculateFoobar(); > >>>>>>> } > >>>>>>> > >>>>>>> Implementation > >>>>>>> > >>>>>>> public class SomeObjectDTO extends DTO implements SomeObject { > >>>>>>> public String foo; > >>>>>>> public String bar; > >>>>>>> > >>>>>>> public SomeObjectDTO() {} > >>>>>>> > >>>>>>> public SomeObjectDTO( String aFoo, String aBar ) { > >>>>>>> foo = aFoo; bar = aBar; > >>>>>>> } > >>>>>>> > >>>>>>> @Override public String foo() { return foo; } > >>>>>>> @Override public String bar() { return bar; } > >>>>>>> @Override public String calculateFoobar() { return foo + “:” + > bar; } > >>>>>>> } > >>>>>>> > >>>>>>> > >>>>>>> I like the above because: > >>>>>>> * No duplication > >>>>>>> * As a DTO, can be sent over the wire and serialised > >>>>>>> * Implements the domain API > >>>>>>> > >>>>>>> > >>>>>>> Cheers, > >>>>>>> =David > >>>>>>> > >>>>>>> > >>>>>> > >>>>> > >>>> > >>>> > >> > >> > >