aspose file tools*
The moose likes Java in General and the fly likes A setter that can only be called by framework Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "A setter that can only be called by framework" Watch "A setter that can only be called by framework" New topic
Author

A setter that can only be called by framework

Pho Tek
Ranch Hand

Joined: Nov 05, 2000
Posts: 761


FooDTO is a Data Transfer Object. I also have a Foo class which is a domain object which is managed by some ORM framework. I have another class, DTOconverter which will convert between Foo and FooDTO instance. Currently Foo & FooDTO are in different package. And DTOConverter is in a util package.

Is there any way to enforce the condition that the setter setId can only be called by class DTOconverter and never by any client who does this:


Thanks
Ådne Brunborg
Ranch Hand

Joined: Aug 05, 2005
Posts: 208
Originally posted by Pho Tek:
Is there any way to enforce the condition that the setter setId can only be called by class DTOconverter


The following might work:



but it is rather, shall we say, "hairy".

Instead, I recommend exploring the possibilities of your framework, which might have some other way of doing this - intercepting calls to the setter, and do the check in a seperate class completely. Because what I suggested above is not exactly loose coupling, and thus to be avoided if possible.

What framework are you using?
[ November 03, 2006: Message edited by: �dne Brunborg ]

Entia non sunt multiplicanda praeter necessitatem
Pho Tek
Ranch Hand

Joined: Nov 05, 2000
Posts: 761

I am using BEA KODO (for the persistence framework). Thanks for the solution.
Ådne Brunborg
Ranch Hand

Joined: Aug 05, 2005
Posts: 208
Of course, this solution is intended to be called with "this" (i.e. the calling object) as the first parameter. There is nothing to stop callers from using "new DTOconverter" instead and thus fool the check.

I don't know BEA tools, but I strongly recommend you try to find some BEA way of doing this. Maybe this page can help?
[ November 03, 2006: Message edited by: �dne Brunborg ]
pascal betz
Ranch Hand

Joined: Jun 19, 2001
Posts: 547
Another one for the "hairy" section :-)
Use a Thread local to store a "magic key". In the converter set the magic key to the Thread local. In the setId() method get the magic key, compare it using DTOConverter.isValidMagicKey(key).

As said: hairy :-)

You could examin the caller stack but this is also hairy, probably slow and might be dependant on JVM.

Or you could just trust the programmers ?

pascal
fred Joly
Ranch Hand

Joined: Jan 19, 2006
Posts: 55
Now you want something hairy...

You could put the "setId" method private.
An then call this method by reflection from
your DTO converter.
An exemple : Reflection/Private
Ådne Brunborg
Ranch Hand

Joined: Aug 05, 2005
Posts: 208
There is also the simple solution of making the setters protected and put them in the same package as the converter, but that is rather old-fashioned and a little boring.
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
You could eliminate the setters on the DTO and make DTOConverter pass all values to a constructor. If there are too many fields for that, you could make a MutableDTO parameter to the ImmutableDTO constructor. That's starting to seem like a lot of effort to prevent ... exactly what bad thing from happening?


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
It sounds like probably the goal is to have the DTO to be immutable after the initial building phase. It's not at all uncommon for DTOs to have too many fields for it to be practical to initialize everything in the constructor. And for my taste, I think anything more than two or three fields is too many - I dislike seeing constructors with long lists of arguments whose significance can be determined only by their order.

So, I like Stan's suggestion of having a MutableDTO and ImmutableDTO - though I'm not sure I understand the "make a MutableDTO parameter to the ImmutableDTO constructor" comment. I like the idea of having the two classes related much like StringBuilder and String. You have a mutable class that you can do whatever you want with, and then when the data is set the way you want, you convert to the immutable version with a toString() method - or toImmutableDTO() method, as the case may be. You can probably find a better name. I like the idea that a FooDTO should have a mutable FooDTOBuilder, or perhaps a nested class FooDTO.Builder. Unfortunately, it's a bit tedious to write a mutable builder class for every DTO, unless you're using code generation of some sort.

An alternative that may be a bit simpler to code is to create a freeze() method which, once you call it once, it becomes impossible to make any further changes to the object. I shamelessly stole this idea from Ruby and played around with it a bit, but haven't applied it on a real project. Here's what I came up with:

This makes it fairly easy to write classes like Foo. The immutability is enforced at runtime rather than compile time, which is a bit unfortunate, but it should work. Something to consider, anyway.
[ November 03, 2006: Message edited by: Jim Yingst ]

"I'm not back." - Bill Harding, Twister
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
To answer the original question as it was asked (assuming you don't like the other suggestions better): I think you could probably do this using a SecurityManager (for enforcement at runtime), or using AspectJ (enforcing at compile time or runtime, depending how you set it up). Either approach would require some extra effort learning the details of how these technologies work, if not already familiar. Personally, I'd pursue the ideas about making the DTOs immutable, before trying either of these approaches.
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
though I'm not sure I understand the "make a MutableDTO parameter to the ImmutableDTO constructor" comment.

Ah, my notion was something like:

Immutable could use gets() on mutable and assign its own variables directly with no setters at all.

I like your notion that the mutable object is a factory or somehow renders itself as the immutable one. Makes the immutable one have no dependence on the mutable one. Would the mutable one use a bunch of protected or package scope setters to load the immutable?

There's nothing to prevent anyone from using the mutable one. Maybe it has no public getters which would make it useless outside the package?

Good puzzle anyhow!
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Stan - thanks for the clarification. The ImmutableDTO(MutableDTO) constructor seems fairly obvious in retrospect, but somehow I was thinking you meant something else. Never mind. It's certainly one of the possible ways to go from mutable to immutable object, and not a bad one. I tend to avoid calling constructors directly in many of my classes, preferring factory methods of one sort or another. But that's a minor difference - it wouldn't be hard to replace your constructor above with ImmutableDTO.createFrom(MutableDTO) method. Either way there's another minor tedious bit I'd like to avoid, where you have to write a copy constructor or something similar, transferring all values from the MutableDTO to the ImmutableDTO.

[Stan]: I like your notion that the mutable object is a factory or somehow renders itself as the immutable one. Makes the immutable one have no dependence on the mutable one. Would the mutable one use a bunch of protected or package scope setters to load the immutable?

Well, I tend to favor making the mutable Builder a nested class inside the class it's supposed to build. That way it has direct access to the private variables of the top-level class. In reality this is implemented with package-access synthetic mutator methods. But as long as I don't have to write them or look at them, I'm happy.

[Stan]: There's nothing to prevent anyone from using the mutable one. Maybe it has no public getters which would make it useless outside the package?

Yeah, I go back and forth over which of those I prefer. Consider String vs. StringBuilder - neither is a subtype of the other. You can write a method that requires a String parameter, and you will get an immutable String, period. Whether it was originally constructed with a StringBuilder is irrelevant. Or, you can write a method which takes a CharSequence parameter, which may be a String, or StringBuilder, or something else. In general one might think it's good to write to the more general interface, but not always. Here is a recent example of how that can cause confusion. That's one of the reasons I like immutable types where possible.

Here's an idea I had for making a reasonably simple mutable Builder / immutable DTO pair:

The getters and setters are easy to auto-generate an any major IDE, but the build() method requires a bit more tedious work. Well, tedious if there are 20 or 100 rather than the mere 2 in this example. Or one can fiddle about with code generation to take care of it. But I'd prefer something that scales better as the number of fields increases, with less redundant code. We can use the Prototype pattern, implement Cloneable, and let clone() take care of all the copying:

This still seems like an annoying amount of boilerplate code for something that really should be simpler, in my opinion. But that's what I've come up with so far, in my attempts to reconcile my preference for immutable objects with my dislike of constructors with long lists of unlabeled arguments. Open to further suggestions...
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
People who have trouble moving from other styles to OO often complain that OO seems to introduce a lot of complexity to achieve simple design goals. I'm feeling that way, now, too. I kinda like where you're going, but I'd look to a code generator for builders and avert my eyes from the generated code.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Yeah, agreed. But even using code generators - what would you want them to build? Or maybe the details don't matter as much as long as you usually don't need to look inside the generated code.
 
wood burning stoves
 
subject: A setter that can only be called by framework