Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Complex Case and the Observer Pattern (A story of JTextFields and Documents)

16 views
Skip to first unread message

Caleb Land

unread,
Apr 22, 2002, 3:40:42 PM4/22/02
to
Hello,
I think I'm running into what's called the "complex case" in the bible
of design patterns (Design Patterns).

My application uses the swing GUI, and I have an abstract model class,
and an ApplicationModel subclass of that class that implements the
observer pattern and fires events when the setX methods are used.

I want my application to allow multiple views to stay up to date at
every keystroke, not just when the user hits the OK button.

My problem is:

I have a dialog that listens for changes in the model, and when such a
change occurs, updates the correct JTextField with the data from the
model using the "setText" method of the textfield. But, I also need to
change the model when the user types text into the field, so I attached
a document listener to the text field's document, and when the user adds
or removes text, I call the model's "setX" method (where X is the field
to be changed), however, this fires an event that the model has been
changed, which notifies the dialog, which changes the textfield, which
fires the document changed events, and so on.

The Design Pattern book mentions a ChangeManager singleton class that
manages changes, but I don't know the best way to implement this.

I thought about subclassing PlainDocument to somehow provide a method to
change the contents of the document without fireing events (or to
provide some sort of "freeze" and "thaw" methods so that when the
document was frozen changes could be made without sending events), but I
have no idea how to do this.

I also thought of maybe keeping a Document instance of a field in the
model so that a textfield could simply use that document as a model, but
this doesn't seem very elegant.

I *did* try installing a keylistener instead of using a
documentlistener, but that is very weak, and though it worked in a basic
level, wasn't very good.

It seems that my problem stems from having two different models to work
with, 1) I have my own model which stores the information in Strings,
and I have the Document model which is used by the JTextFields

How do you more proficient and experienced programmers deal with a
situation like this?

-Caleb Land
(bok...@rochester.rr.com)

Caleb Land

unread,
Apr 22, 2002, 4:13:56 PM4/22/02
to
Caleb Land wrote:
> It seems that my problem stems from having two different models to work
> with, 1) I have my own model which stores the information in Strings,
> and I have the Document model which is used by the JTextFields


I think I also found another problem. Apparently, when one uses the
setText JTextField method, it clears the document to nothing and then
inserts the text, generating events in the meanwhile that say that the
text entry is empty...
-Caleb

Kleopatra

unread,
Apr 22, 2002, 4:56:55 PM4/22/02
to

Caleb Land schrieb:


>
> My application uses the swing GUI, and I have an abstract model class,
> and an ApplicationModel subclass of that class that implements the
> observer pattern and fires events when the setX methods are used.

one possibility to break the repeated round trip notification is to
notify only if setXX actually did change the state - don't fire if it's
the same as before. You can do so both on your application model and
on the ui model, that is the documnet in your case.

To decouple both models I usually introduce a listening layer between
them - in the general case you need to do some conversion between
application model vocabulary and ui model anyway. The listening layer
takes the change notification from one of them, converts into the voc of
the other and only calls the setX or equivalent on the target if a
change has been detected.

Greetings
Jeanette

Maurice Naftalin

unread,
Apr 22, 2002, 6:09:55 PM4/22/02
to
Caleb Land wrote:

> My problem is:
>
> I have a dialog that listens for changes in the model, and when such a
> change occurs, updates the correct JTextField with the data from the
> model using the "setText" method of the textfield. But, I also need to
> change the model when the user types text into the field, so I attached
> a document listener to the text field's document, and when the user adds
> or removes text, I call the model's "setX" method (where X is the field
> to be changed), however, this fires an event that the model has been
> changed, which notifies the dialog, which changes the textfield, which
> fires the document changed events, and so on.
>

> I thought about subclassing PlainDocument to somehow provide a method to
> change the contents of the document without fireing events (or to
> provide some sort of "freeze" and "thaw" methods so that when the
> document was frozen changes could be made without sending events), but I
> have no idea how to do this.

I'd advise against this. I've tried both, and they end in tears (and I
think
your opinion of your other two solutions is accurate also).

> How do you more proficient and experienced programmers deal with a
> situation like this?

I look forward to reading what they would do :) Here's what I would
want to do, though it may not work in this case. I would ideally like
to intercept all the calls from JTextField to the insertString(...) and
remove(...) methods of the document, and instead of allowing them
to call the document methods directly, instead call the appropriate
update method of the model, which would then notify the document,
which would then notify the component. This is simple and effective,
though in cases like this it leads to a somewhat brittle solution
because you have to modify methods of the component class and use
the modified versions to override the originals.

Unfortunately the source for JTextComponent shows calls of
insertString(...) and remove(...) in three public methods which can be
simply and reliably overridden, but also one private method,
replaceInputMethodText(...). If that's an important case, you _could_
override the method that calls it (processInputMethodEvent()), but
that calls another private method, so you'll end up with a lot of
borrowed code in your new component class.

To summarise: this is the best solution when you can apply it IME.
Whether this is such a case would require you to work out whether
processInputMethodEvent is going to be used by the JTextField
in your application.

Hope this helps
Maurice

Maurice Naftalin

unread,
Apr 22, 2002, 6:35:23 PM4/22/02
to
Caleb Land wrote:

> I have a dialog that listens for changes in the model, and when such a
> change occurs, updates the correct JTextField with the data from the
> model using the "setText" method of the textfield. But, I also need to
> change the model when the user types text into the field, so I attached
> a document listener to the text field's document, and when the user adds
> or removes text, I call the model's "setX" method (where X is the field
> to be changed), however, this fires an event that the model has been
> changed, which notifies the dialog, which changes the textfield, which
> fires the document changed events, and so on.

The solution I like best is to trap calls from the component to its
Document model (by overriding the component methods that make
the calls) and have them notify your model instead, which then
notifies the Document, which then notifies your component. This is
simple and effective, though it can be be brittle because you may find
you are using modified versions of the component's methods to override
the originals. In this particular case there's an extra problem in that one

of the JTextComponent methods that calls the Document's
insertString(...) and remove(...) methods is private (
replaceInputMethodText(...)), so you would have to override the
method that calls it. I would give up if you have to do that and look
for another solution, but if your application doesn't use that method I
would seriously consider this way of doing it.

Maurice

Caleb Land

unread,
Apr 22, 2002, 7:43:56 PM4/22/02
to
Maurice Naftalin wrote:
> The solution I like best is to trap calls from the component to its
> Document model (by overriding the component methods that make
> the calls) and have them notify your model instead, which then
> notifies the Document, which then notifies your component. This is
> simple and effective, though it can be be brittle because you may find
> you are using modified versions of the component's methods to override
> the originals. In this particular case there's an extra problem in that one
>
> of the JTextComponent methods that calls the Document's
> insertString(...) and remove(...) methods is private (
> replaceInputMethodText(...)), so you would have to override the
> method that calls it. I would give up if you have to do that and look
> for another solution, but if your application doesn't use that method I
> would seriously consider this way of doing it.

I think I understand what you're typing... Let me see if I got this
straight.

You're saying that I might want to subclass the JTextField, overriding
methods which call the document model modification methods
(insertString(...) and remove(...)) and have those methods instead call
my model's setX functions.

My setX function would then notify listeners that something has changed.

What I don't think I understand is how my model should notify the
document of changes to it, should I subclass PlainDocument and add a
notify method so it can be a listener to my model?

Which leads to another question, as it is now, my dialog window (a
subclass of JDialog) registers itself as a listener to my model, and
updates the components when there's been a change, but it seems that
with the above situation, the individual components would listen for
changes in the model (each could register to listen only to changes in
the field that the component represents), though this would require
subclassing of all of the components that I use (comboboxes, textentries
, textfields, etc), or am I not understanding?

Hmmmm, and if the user types some stuff into the box, my modified
methods get called, which instead of calling the document methods, call
my own model methods, which notifies the documents listening to it,
which then notifies the textfield which then updates the display?

I'm quite the newbie at OO, and this is all new and exciting (and
frustrating :))

Whew! Thanks for the help!

-Caleb

Kleopatra

unread,
Apr 23, 2002, 4:58:42 AM4/23/02
to

Maurice Naftalin schrieb:


> want to do, though it may not work in this case. I would ideally like
> to intercept all the calls from JTextField to the insertString(...) and
> remove(...) methods of the document, and instead of allowing them
> to call the document methods directly, instead call the appropriate
> update method of the model, which would then notify the document,
> which would then notify the component. This is simple and effective,
> though in cases like this it leads to a somewhat brittle solution
> because you have to modify methods of the component class and use
> the modified versions to override the originals.

I disagree: that's neither simple (you correctly state one of the issues
below :-) nor efficient and it's definately not in the "spirit of
swing".

> Unfortunately the source for JTextComponent shows calls of
> insertString(...) and remove(...) in three public methods which can be
> simply and reliably overridden, but also one private method,
> replaceInputMethodText(...). If that's an important case, you _could_
> override the method that calls it (processInputMethodEvent()), but
> that calls another private method, so you'll end up with a lot of
> borrowed code in your new component class.
>
> To summarise: this is the best solution when you can apply it IME.

No again: you are fighting the framework if you go along those lines and
that's always a resource wasting (your own time f.i.). Except with very
good reason (bug fixing, customizing of the _view_ in a way that's not
provided by the components...) you _never_ subclass the JXX. When
starting with swing, look at them as a black box that has exactly one
slot to introduce custom functionality and that one slot is the model.
Never fiddle with the internal interaction between view and model - you
will not get it right anyway. Whatever you have to do, do it "on top" of
that black box - there is a very instructive article at the swing
connection dating from the early days of swing (don't have the link
handy at the moment, but you'll find it if you look for it).

Greetings
Jeanette

Maurice Naftalin

unread,
Apr 23, 2002, 5:22:53 AM4/23/02
to
Caleb Land wrote:

> I think I understand what you're typing... Let me see if I got this
> straight.
>
> You're saying that I might want to subclass the JTextField, overriding
> methods which call the document model modification methods
> (insertString(...) and remove(...)) and have those methods instead call
> my model's setX functions.
>
> My setX function would then notify listeners that something has changed.

Yes, that's what I was trying to say.

> What I don't think I understand is how my model should notify the
> document of changes to it, should I subclass PlainDocument and add a
> notify method so it can be a listener to my model?

You could do that, but what would the notify method do? It would call
insertString and remove. The principles of MVC would allow you to
define a method in your model:
addDocumentAsListener( Document d ) { ... }
and another one
fireInsertToListeningDocuments(
int offset, String str, AttributeSet a ) { ... }

What I'm trying to say is that the Document doesn't have to have a
specialised notify method which receives an event - all that matters
is that the change gets notified somehow to the listeners. The
standard way of doing it would be to define a new Listener interface
and corresponding Event class, which is straightforward but might
be unnecessary.

> Which leads to another question, as it is now, my dialog window (a
> subclass of JDialog) registers itself as a listener to my model, and
> updates the components when there's been a change, but it seems that
> with the above situation, the individual components would listen for
> changes in the model (each could register to listen only to changes in
> the field that the component represents), though this would require
> subclassing of all of the components that I use (comboboxes, textentries
> , textfields, etc), or am I not understanding?

If your individual components all register with the central model, your
design may get rather unstructured. If that's going to be a problem,
build it hierarchically - have the model notify the dialog, and then have
the dialog notify its individual components (that hierarchy would be
based on physical structure - there may be others). I think that's
called hierarchical MVC, see
http://www.javaworld.com/javaworld/jw-07-2000/jw-0721-hmvc.html
http://www.jaydeetechnology.co.uk/planetjava/tutorials/swing/hmvc.PDF
(I don't claim to have read these properly myself :))

As for your question about subclassing the components, I don't
think that would be necessary in order to have them reflect changes
in the model state. I would notify the individual component model,
as we have been discussing for your JTextField/PlainDocument
example.

> Hmmmm, and if the user types some stuff into the box, my modified
> methods get called, which instead of calling the document methods, call
> my own model methods, which notifies the documents listening to it,
> which then notifies the textfield which then updates the display?

Yes.

> I'm quite the newbie at OO, and this is all new and exciting (and
> frustrating :))

It's extremely frustrating until you get it to work, and then it's wonderful.

Maurice

Maurice Naftalin

unread,
Apr 23, 2002, 5:35:34 AM4/23/02
to
Kleopatra wrote:

> Maurice Naftalin schrieb:
> ...


> > which would then notify the component. This is simple and effective,
> > though in cases like this it leads to a somewhat brittle solution
> > because you have to modify methods of the component class and use
> > the modified versions to override the originals.
>
> I disagree: that's neither simple (you correctly state one of the issues
> below :-) nor efficient and it's definately not in the "spirit of
> swing".

Simple is a matter of taste, and I'm not concerned about the
performance overhead, which I think is small anyway. I
don't like to think that I'm going against the "spirit of swing",
though. But I'm not convinced about this.

> No again: you are fighting the framework if you go along those lines and
> that's always a resource wasting (your own time f.i.). Except with very
> good reason (bug fixing, customizing of the _view_ in a way that's not
> provided by the components...) you _never_ subclass the JXX. When
> starting with swing, look at them as a black box that has exactly one
> slot to introduce custom functionality and that one slot is the model.
> Never fiddle with the internal interaction between view and model - you
> will not get it right anyway. Whatever you have to do, do it "on top" of
> that black box - there is a very instructive article at the swing
> connection dating from the early days of swing (don't have the link
> handy at the moment, but you'll find it if you look for it).

If it was really the case that you could not intervene between
view and model, would that not be an indication of close
coupling (and poor design)? Why separate the delegate
and component at all if you then have to view them as a
black box? It certainly isn't true that you can't get such
interventions right - I have done, often, and it isn't hard.
The only place where I have never succeeded is with the
layout cache for JTree, which is a kind of model of the
expansion state of the tree but does not conform to any
of the model conventions. But I think that that particular
part of Swing isn't well thought out.

Still, I take your criticism of fighting the framework
seriously. Is there anything you can point to, to back
that up?

Maurice

Kleopatra

unread,
Apr 23, 2002, 9:36:58 AM4/23/02
to

Maurice Naftalin schrieb:


>
> Kleopatra wrote:
>
> > Maurice Naftalin schrieb:
> > ...
> > > which would then notify the component. This is simple and effective,
> > > though in cases like this it leads to a somewhat brittle solution
> > > because you have to modify methods of the component class and use
> > > the modified versions to override the originals.
> >
> > I disagree: that's neither simple (you correctly state one of the issues
> > below :-) nor efficient and it's definately not in the "spirit of
> > swing".
>
> Simple is a matter of taste, and I'm not concerned about the
> performance overhead, which I think is small anyway. I
> don't like to think that I'm going against the "spirit of swing",
> though. But I'm not convinced about this.

Actually I don't care about performance until it hit's me into the face,
I just quoted your words "simple and effective". As to the issue of
simplicity, I don't think that fiddling with implementation details
(such as c&p of view's private methods) just to go an unnecessaryly
complicated solution path is a matter of taste, it's suboptimal
programming practice to me. My opinion, of course you are free to
disagree.



>
> > No again: you are fighting the framework if you go along those lines and
> > that's always a resource wasting (your own time f.i.). Except with very
> > good reason (bug fixing, customizing of the _view_ in a way that's not
> > provided by the components...) you _never_ subclass the JXX. When
> > starting with swing, look at them as a black box that has exactly one
> > slot to introduce custom functionality and that one slot is the model.
> > Never fiddle with the internal interaction between view and model - you
> > will not get it right anyway. Whatever you have to do, do it "on top" of
> > that black box - there is a very instructive article at the swing
> > connection dating from the early days of swing (don't have the link
> > handy at the moment, but you'll find it if you look for it).
>
> If it was really the case that you could not intervene between
> view and model, would that not be an indication of close
> coupling (and poor design)? Why separate the delegate
> and component at all if you then have to view them as a
> black box?

By "delegate" you mean the model, right? In my opinion the coupling
between JXX and its model is the optimized loosest coupling possible -
in the context of the framework. Whatever you introduce in between the
two you tighten the coupling, and by your own definition make the design
worse. With your suggestion you introduced a tight coupling from the
JTextfield to the (business!) model plus a coupling from the model to
the document.

Any given view has exactly one _type_ of model that it can deal with -
changing that _type_ would mean to introduce a new view. The value in
separating the two is that you can provide any implementation of it that
fulfills the models contract and fits your needs. There are cases when
you need a totally new view-model pairing, but then call it by it's
name: a JTextfield that does not have a document as model is _not_ a
JTextField but a JMyView acting on MyModel with (maybe) the look of a
JTextField.

Now let's come back to the original problem: it's simply a problem of
keeping two models in different realms in synch (one near the view and
the other near the application layer) without going into an endless loop
on notification. Note that it resides totally in the model layer - so it
should be solved in the model layer. That's exactly where the benefits
of separating model and view can show up: _it is_ easily possible to
solve it in the model realm without bothering with the view.

>
> Still, I take your criticism of fighting the framework
> seriously. Is there anything you can point to, to back
> that up?

As I mentioned in my earlier post, there is an ancient article at the
swingconnection, it shows the benefits of using adapter everywhere...

Greetings
Jeanette

Maurice Naftalin

unread,
Apr 23, 2002, 11:05:48 AM4/23/02
to
Kleopatra wrote:

> Maurice Naftalin schrieb:
> >


> > If it was really the case that you could not intervene between
> > view and model, would that not be an indication of close
> > coupling (and poor design)? Why separate the delegate
> > and component at all if you then have to view them as a
> > black box?
>
> By "delegate" you mean the model, right? In my opinion the coupling
> between JXX and its model is the optimized loosest coupling possible -
> in the context of the framework. Whatever you introduce in between the
> two you tighten the coupling, and by your own definition make the design
> worse. With your suggestion you introduced a tight coupling from the
> JTextfield to the (business!) model plus a coupling from the model to
> the document.

Sorry, "delegate" means the combined view/controller. That was a
typo, I meant to say "why separate delegate and model". But I'm
not proposing to tighten the coupling, I want to replace one loose
coupling with another. And having a component talk to a business
model isn't a specially bad thing - it's the standard thing that we do
with tables and trees all the time.

> Any given view has exactly one _type_ of model that it can deal with -
> changing that _type_ would mean to introduce a new view. The value in
> separating the two is that you can provide any implementation of it that
> fulfills the models contract and fits your needs. There are cases when
> you need a totally new view-model pairing, but then call it by it's
> name: a JTextfield that does not have a document as model is _not_ a
> JTextField but a JMyView acting on MyModel with (maybe) the look of a
> JTextField.
>
> Now let's come back to the original problem: it's simply a problem of
> keeping two models in different realms in synch (one near the view and
> the other near the application layer) without going into an endless loop
> on notification. Note that it resides totally in the model layer - so it
> should be solved in the model layer. That's exactly where the benefits
> of separating model and view can show up: _it is_ easily possible to
> solve it in the model realm without bothering with the view.
>
> >
> > Still, I take your criticism of fighting the framework
> > seriously. Is there anything you can point to, to back
> > that up?
>
> As I mentioned in my earlier post, there is an ancient article at the
> swingconnection, it shows the benefits of using adapter everywhere...

The only thing that I could find that seems to fit your description is at
http://java.sun.com/products/jfc/tsc/articles/architecture/index.html
and I'm afraid I can't see how that supports your viewpoint at all - in
fact it emphasises application-data models, which have "meaning
primarily in the context of the application", i.e. business models.

In a spirit of compromise, though, how about this, which I should have
thought of before: rather than subclassing the component, which
neither of us likes, why not subclass the model, Document say, to
override the insertString method with
public void insertString( ... ) {
businessModel.insertString(...);
}
and from the business model call a new or overloaded method in the
Document subclass like
public void insertStringFromBusinessModel( ... ) {
super.insertString( ... );
}
Does that meet any of your objections?

One place I have found in which you just have to do it my way
is when a model is multithreaded. If you need to be able to
prevent the user from changing the model because it's locked
against her, then you _have_ to route the change request through
the model before you allow the component to be changed.

Maurice

Maurice Naftalin

unread,
Apr 23, 2002, 11:06:00 AM4/23/02
to
Kleopatra wrote:

> Maurice Naftalin schrieb:
> >


> > If it was really the case that you could not intervene between
> > view and model, would that not be an indication of close
> > coupling (and poor design)? Why separate the delegate
> > and component at all if you then have to view them as a
> > black box?
>
> By "delegate" you mean the model, right? In my opinion the coupling
> between JXX and its model is the optimized loosest coupling possible -
> in the context of the framework. Whatever you introduce in between the
> two you tighten the coupling, and by your own definition make the design
> worse. With your suggestion you introduced a tight coupling from the
> JTextfield to the (business!) model plus a coupling from the model to
> the document.

Sorry, "delegate" means the combined view/controller. That was a


typo, I meant to say "why separate delegate and model". But I'm
not proposing to tighten the coupling, I want to replace one loose
coupling with another. And having a component talk to a business
model isn't a specially bad thing - it's the standard thing that we do
with tables and trees all the time.

> Any given view has exactly one _type_ of model that it can deal with -


> changing that _type_ would mean to introduce a new view. The value in
> separating the two is that you can provide any implementation of it that
> fulfills the models contract and fits your needs. There are cases when
> you need a totally new view-model pairing, but then call it by it's
> name: a JTextfield that does not have a document as model is _not_ a
> JTextField but a JMyView acting on MyModel with (maybe) the look of a
> JTextField.
>
> Now let's come back to the original problem: it's simply a problem of
> keeping two models in different realms in synch (one near the view and
> the other near the application layer) without going into an endless loop
> on notification. Note that it resides totally in the model layer - so it
> should be solved in the model layer. That's exactly where the benefits
> of separating model and view can show up: _it is_ easily possible to
> solve it in the model realm without bothering with the view.
>
> >
> > Still, I take your criticism of fighting the framework
> > seriously. Is there anything you can point to, to back
> > that up?
>
> As I mentioned in my earlier post, there is an ancient article at the
> swingconnection, it shows the benefits of using adapter everywhere...

The only thing that I could find that seems to fit your description is at

Maurice Naftalin

unread,
Apr 23, 2002, 11:06:49 AM4/23/02
to
Kleopatra wrote:

> Maurice Naftalin schrieb:
> >


> > If it was really the case that you could not intervene between
> > view and model, would that not be an indication of close
> > coupling (and poor design)? Why separate the delegate
> > and component at all if you then have to view them as a
> > black box?
>
> By "delegate" you mean the model, right? In my opinion the coupling
> between JXX and its model is the optimized loosest coupling possible -
> in the context of the framework. Whatever you introduce in between the
> two you tighten the coupling, and by your own definition make the design
> worse. With your suggestion you introduced a tight coupling from the
> JTextfield to the (business!) model plus a coupling from the model to
> the document.

Sorry, "delegate" means the combined view/controller. That was a


typo, I meant to say "why separate delegate and model". But I'm
not proposing to tighten the coupling, I want to replace one loose
coupling with another. And having a component talk to a business
model isn't a specially bad thing - it's the standard thing that we do
with tables and trees all the time.

> Any given view has exactly one _type_ of model that it can deal with -


> changing that _type_ would mean to introduce a new view. The value in
> separating the two is that you can provide any implementation of it that
> fulfills the models contract and fits your needs. There are cases when
> you need a totally new view-model pairing, but then call it by it's
> name: a JTextfield that does not have a document as model is _not_ a
> JTextField but a JMyView acting on MyModel with (maybe) the look of a
> JTextField.
>
> Now let's come back to the original problem: it's simply a problem of
> keeping two models in different realms in synch (one near the view and
> the other near the application layer) without going into an endless loop
> on notification. Note that it resides totally in the model layer - so it
> should be solved in the model layer. That's exactly where the benefits
> of separating model and view can show up: _it is_ easily possible to
> solve it in the model realm without bothering with the view.
>
> >
> > Still, I take your criticism of fighting the framework
> > seriously. Is there anything you can point to, to back
> > that up?
>
> As I mentioned in my earlier post, there is an ancient article at the
> swingconnection, it shows the benefits of using adapter everywhere...

The only thing that I could find that seems to fit your description is at

Maurice Naftalin

unread,
Apr 23, 2002, 11:07:30 AM4/23/02
to
Kleopatra wrote:

> Maurice Naftalin schrieb:
> >


> > If it was really the case that you could not intervene between
> > view and model, would that not be an indication of close
> > coupling (and poor design)? Why separate the delegate
> > and component at all if you then have to view them as a
> > black box?
>
> By "delegate" you mean the model, right? In my opinion the coupling
> between JXX and its model is the optimized loosest coupling possible -
> in the context of the framework. Whatever you introduce in between the
> two you tighten the coupling, and by your own definition make the design
> worse. With your suggestion you introduced a tight coupling from the
> JTextfield to the (business!) model plus a coupling from the model to
> the document.

Sorry, "delegate" means the combined view/controller. That was a


typo, I meant to say "why separate delegate and model". But I'm
not proposing to tighten the coupling, I want to replace one loose
coupling with another. And having a component talk to a business
model isn't a specially bad thing - it's the standard thing that we do
with tables and trees all the time.

> Any given view has exactly one _type_ of model that it can deal with -


> changing that _type_ would mean to introduce a new view. The value in
> separating the two is that you can provide any implementation of it that
> fulfills the models contract and fits your needs. There are cases when
> you need a totally new view-model pairing, but then call it by it's
> name: a JTextfield that does not have a document as model is _not_ a
> JTextField but a JMyView acting on MyModel with (maybe) the look of a
> JTextField.
>
> Now let's come back to the original problem: it's simply a problem of
> keeping two models in different realms in synch (one near the view and
> the other near the application layer) without going into an endless loop
> on notification. Note that it resides totally in the model layer - so it
> should be solved in the model layer. That's exactly where the benefits
> of separating model and view can show up: _it is_ easily possible to
> solve it in the model realm without bothering with the view.
>
> >
> > Still, I take your criticism of fighting the framework
> > seriously. Is there anything you can point to, to back
> > that up?
>
> As I mentioned in my earlier post, there is an ancient article at the
> swingconnection, it shows the benefits of using adapter everywhere...

The only thing that I could find that seems to fit your description is at

Kleopatra

unread,
Apr 23, 2002, 12:15:43 PM4/23/02
to

Maurice Naftalin schrieb:
> > > If it was really the case that you could not intervene between
> > > view and model, would that not be an indication of close
> > > coupling (and poor design)? Why separate the delegate
> > > and component at all if you then have to view them as a
> > > black box?
> >
> > By "delegate" you mean the model, right? In my opinion the coupling
> > between JXX and its model is the optimized loosest coupling possible -
> > in the context of the framework. Whatever you introduce in between the
> > two you tighten the coupling, and by your own definition make the design
> > worse. With your suggestion you introduced a tight coupling from the
> > JTextfield to the (business!) model plus a coupling from the model to
> > the document.
>
> Sorry, "delegate" means the combined view/controller. That was a
> typo, I meant to say "why separate delegate and model".

okay then it does not change much on the argument, it's always model and
view/including controller.

> But I'm
> not proposing to tighten the coupling, I want to replace one loose
> coupling with another. And having a component talk to a business
> model isn't a specially bad thing - it's the standard thing that we do
> with tables and trees all the time.

I never said anything against custom models - as long as they _are_
documents... (in the special case of JTextComponents). Maybe I misread
your initial statement:

"I would ideally like
to intercept all the calls from JTextField to the insertString(...) and
remove(...) methods of the document, and instead of allowing them
to call the document methods directly, instead call the appropriate

update method of the model, which would then notify the document,


which would then notify the component."

To me that reads like triangle with each corner being a distinct object:
JTextField talks to the business model "instead of ... (calling) the
document methods directly" which talks to the document which in turn
notifies the JTextField. Only in this szenario would you need to
subclass JTextfield ("intercept all the calls") which you suggested (and
elaborated on later in your post). If you meant to have your business
model implement the document model and internally have some document to
delegate to, that's a totally different beast but then I can't see the
need to subclass the JTextField as it will deal with a Document as
always.

Implementing the Document with the business model is a stronger coupling
than using an adapter between business model and view model (= document)
as I suggested in my reply to the OP, choosing between both approaches
is a matter of taste, agreed. Personally I prefer the adapter approach
(which is outlined in the second part of the Magelang short course to
swing at
http://developer.java.sun.com/developer/onlineTraining/GUI/Swing2/index.html,
and not in the swingconnection sorry for the confusion on this, I should
have checked before).

>
> In a spirit of compromise, though, how about this, which I should have
> thought of before: rather than subclassing the component, which
> neither of us likes, why not subclass the model, Document say, to
> override the insertString method with
> public void insertString( ... ) {
> businessModel.insertString(...);
> }
> and from the business model call a new or overloaded method in the
> Document subclass like
> public void insertStringFromBusinessModel( ... ) {
> super.insertString( ... );
> }
> Does that meet any of your objections?

Looks okay, though I would not do it that way, at least not generally
and not if the business model has many different aspects. As I stated
above, I usually use a layered approach then.

>
> One place I have found in which you just have to do it my way
> is when a model is multithreaded. If you need to be able to
> prevent the user from changing the model because it's locked
> against her, then you _have_ to route the change request through
> the model before you allow the component to be changed.

Hmm, I don't quite see that (you can have a locked model
implementation, can't you?) but I can accept it as an argument - I'm not
in multithreaded environments.

To sum up, the important point I wanted to make is that there generally
is _no_ reason to subclass the view - though there might be for special
reasons. And the original problem does not qualify for "special reason",
in my opinion. I think we can agree somewhere along those lines.

Greetings
Jeanette

Caleb Land

unread,
Apr 23, 2002, 4:29:15 PM4/23/02
to
Maurice Naftalin wrote:

> In a spirit of compromise, though, how about this, which I should have
> thought of before: rather than subclassing the component, which
> neither of us likes, why not subclass the model, Document say, to
> override the insertString method with
> public void insertString( ... ) {
> businessModel.insertString(...);
> }
> and from the business model call a new or overloaded method in the
> Document subclass like
> public void insertStringFromBusinessModel( ... ) {
> super.insertString( ... );
> }

What if I subclassed Document, and set it up like one would a TableModel
class where you overload the document's model altering, and retrieving
methods to my own model's methods? IE

public class MyDocument extends Document {
public MyDocument (BusinessModel bm) {
...


}
public void insertString( ... ) {
businessModel.insertString(...);
}

public String getText( ... ) {
businessModel.getText ( ... );
}
public void remove( ... ) {
businessModel.remove ( ... );
}
...
}

This wouldn't use the document's default storage at all, and instead
would use only my model for storage (like a jtablemodel does).

I admit, I'm ignorant of documents (I have the O'Reilly Swing book, but
have yet to read the document section in depth), so I don't know if this
would break anything. It seems as though this would prevent me from
using fonts and such, but I don't need that, and I'm sure there would be
a way to add it.

--Caleb
(bok...@rochester.rr.com)

Maurice Naftalin

unread,
Apr 24, 2002, 12:17:37 PM4/24/02
to
Caleb Land wrote:

I may have misled you here by my careless use of "Document" in
the message you're replying to. Document is an interface, implemented
in javax.swing.text by two classes, PlainDocument and
DefaultStyledDocument. Take a look at the Javadoc for Document
and you'll see that implementing the interface isn't straightforward,
because Documents are assumed to have a logical structure of elements,
which components are entitled to depend on. (In fact the facilities
provided by PlainDocument are way over those that are used by the
plain text controls - for example, it's supposed to be possible to provide
different text attributes for each line of a PlainDocument), so you
probably could get away with something much simpler, but I don't
think anyone ever reimplements the Document interface from scratch.
It would be a lot of work for no very great gain. And if instead of
that you subclassed from PlainDocument, your overrides would
give back content that would be inconsistent with the state of the
PlainDocument.

I should have been clearer that (in the context of the plain text
components) it was PlainDocument that I was thinking of subclassing
in the way that I suggested. And I think it will only work if you use
the PlainDocument's facilities to actually store the text.

Maurice

0 new messages