Ya, kinda... for how we use model driven we probably should be using the
scoped version, but that's not the case. We have an abstract action that
handles the validation/refreshing/storing of the model in the session. It's
overkill, but it's heavily unit tested and robust, so we continue using it.
On Mon, Oct 7, 2013 at 4:12 PM, Dave Newton <davelnewton@gmail.com> wrote:
> You mean like ScopedModelDriven?
>
> I'm a big fan of presenters/decorators most of the time, although I'll
> admit I'm also lazy a lot and just use a "real" model and tags :/
>
> Dave
>
>
>
> On Mon, Oct 7, 2013 at 5:08 PM, Mike Menzies <glopal@gmail.com> wrote:
>
> > Hmm.. ya, that makes a lot of sense. I think I will try this approach
> going
> > forward. We sort of bastardize model-driven a little bit by having a
> layer
> > that stores and retrieves the model in the session on every request
> (among
> > other things)... which in most cases is not needed.
> >
> > You've given me some things to think about. Thanks Dave.
> >
> >
> > On Mon, Oct 7, 2013 at 4:00 PM, Dave Newton <davelnewton@gmail.com>
> wrote:
> >
> > > "The" model? "The" model is whatever you want exposed to the view
> layer;
> > > there's nothing that states it has to be the lowest-level domain object
> > > available--it's just "that which you wish exposed to your rendering".
> > >
> > > I don't usually use the built-in validations (for a variety of reasons)
> > so
> > > I'd have to experiment with that to find what I liked.
> > >
> > > Dave
> > >
> > >
> > > On Mon, Oct 7, 2013 at 4:56 PM, Mike Menzies <glopal@gmail.com> wrote:
> > >
> > > > I can see that approach working well. You don't feel that it's
> misusing
> > > > ModelDriven... by not directly returning the model? Also, if you are
> > > > validating your model, would adding @VisitorFieldValidator to the
> > domain
> > > > getter within the decorator work the same?
> > > >
> > > >
> > > > On Mon, Oct 7, 2013 at 3:43 PM, Dave Newton <davelnewton@gmail.com>
> > > wrote:
> > > >
> > > > > Then I'm not sure I see the point; `ModelDriven` would do the same,
> > but
> > > > > you'd expose the decorator, not the underlying domain object. I
> tend
> > > > > towards the same pattern, but delegate directly to a domain model,
> > so I
> > > > can
> > > > > precisely control access (and document) at the view level.
> > > > >
> > > > > Dave
> > > > >
> > > > >
> > > > >
> > > > > On Mon, Oct 7, 2013 at 4:38 PM, Mike Menzies <glopal@gmail.com>
> > wrote:
> > > > >
> > > > > > Yes. That's pretty much exactly what it is.
> > > > > >
> > > > > >
> > > > > > On Mon, Oct 7, 2013 at 3:35 PM, Dave Newton <
> davelnewton@gmail.com
> > >
> > > > > wrote:
> > > > > >
> > > > > > > So it's a presenter/decorator?
> > > > > > >
> > > > > > > Dave
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > On Mon, Oct 7, 2013 at 4:26 PM, Mike Menzies <glopal@gmail.com
> >
> > > > wrote:
> > > > > > >
> > > > > > > > Hello,
> > > > > > > >
> > > > > > > > My name is Mike, and I work for a fairly large company
that
> > uses
> > > > > > Struts 2
> > > > > > > > for most of its web apps. Some of these web apps are
quite
> > large,
> > > > and
> > > > > > one
> > > > > > > > in particular has grown into a monster. In my ongoing
efforts
> > to
> > > > > clean
> > > > > > up
> > > > > > > > this project, I have developed what I like to call
a
> JspHelper.
> > > > > Before
> > > > > > I
> > > > > > > > explain exactly what that is, I'd like to provide
you with
> some
> > > > > > examples
> > > > > > > of
> > > > > > > > the problems that I set out to fix.
> > > > > > > >
> > > > > > > > *Problem 1 - Monster JSPs*
> > > > > > > > During early development of this project, struts tags
were
> > highly
> > > > > > > > leveraged. I was not involved with the early phases
of this
> > > > project,
> > > > > > so I
> > > > > > > > can't speak to why they were used so extensively..
but they
> > were.
> > > > > Tons
> > > > > > of
> > > > > > > > nested if tags that read var tags that were set in
the JSP.
> > Some
> > > of
> > > > > > these
> > > > > > > > JSPs were very hard to follow.
> > > > > > > >
> > > > > > > > Even though I am a fan of struts tags, I've come to
realize
> > that
> > > > they
> > > > > > > > should not be overused. JSPs cannot be unit tested
and JSPs
> are
> > > > hard
> > > > > to
> > > > > > > > debug.
> > > > > > > >
> > > > > > > > So cleaning up a JSP means shifting logic out, in
most cases
> > into
> > > > the
> > > > > > > > action. An easy clean up could be something like this:
> > > > > > > >
> > > > > > > > <s:if test="articles != null && articles.size
> 0 &&
> > > > > > > user.canViewArticles">
> > > > > > > >
> > > > > > > > into
> > > > > > > >
> > > > > > > > <s:if test="showArticleSection()">
> > > > > > > >
> > > > > > > > It's instantly more readable, and the logic is in
a testable
> > Java
> > > > > > class.
> > > > > > > > Following this approach creates a lot of methods in
the
> action,
> > > > which
> > > > > > can
> > > > > > > > be a problem if you already have...
> > > > > > > >
> > > > > > > > *Problem 2 - Bloated Action Classes*
> > > > > > > >
> > > > > > > > When the project was small, it made a lot of sense
to create
> > > > > > > > abstract/parent action classes to share code between
actions.
> > As
> > > > time
> > > > > > > > passed, we just continued shoving any shared code
in one of
> two
> > > > > > > "abstract"
> > > > > > > > classes... even if the code was only being shared
between two
> > out
> > > > of
> > > > > > the
> > > > > > > 20
> > > > > > > > actions.
> > > > > > > >
> > > > > > > > The fix for this trend is to moved shared code into
services,
> > so
> > > we
> > > > > > began
> > > > > > > > enforcing that practice. But this approach had its
> limitations.
> > > We
> > > > > use
> > > > > > > > Spring injection for all of our services, and some
times a
> > > > particular
> > > > > > > piece
> > > > > > > > of logic just required too much stateful input...
it just
> made
> > > more
> > > > > > sense
> > > > > > > > to leave it on the action where it had easy access
to
> > everything
> > > it
> > > > > > > needed,
> > > > > > > > as opposed to shoving it in a stateless service and
having to
> > > pass
> > > > > in a
> > > > > > > ton
> > > > > > > > of arguments.
> > > > > > > >
> > > > > > > > What we really needed was some best practices put
in place
> for
> > > the
> > > > > > > creation
> > > > > > > > of stateful, non-Spring services.
> > > > > > > >
> > > > > > > > *Enter JspHelperInceptor
> > > > > > > >
> > > > > > > > *
> > > > > > > > It wasn't until after I created this inceptor that
I realized
> > it
> > > is
> > > > > > > almost
> > > > > > > > identical to the ModelDrivenInceptor. At which point,
I
> > wondered
> > > if
> > > > > > that
> > > > > > > is
> > > > > > > > what I should actually be using.. but more on that
later.
> > > > > > > >
> > > > > > > > All this interceptor does is push an object onto the
value
> > stack.
> > > > > > That's
> > > > > > > > it. Your action implements JspHelperAware which provides
> Object
> > > > > > > > getJspHelper(), and the intercept code reads almost
line for
> > line
> > > > > with
> > > > > > > the
> > > > > > > > ModelDrivenInterceptor.
> > > > > > > >
> > > > > > > > The idea behind this JspHelper, which is just a POJO
that you
> > > > define,
> > > > > > is
> > > > > > > to
> > > > > > > > provide a place where all (or most) of the data your
JSP
> needs
> > > can
> > > > be
> > > > > > > > found. This means that OGNL can find any public members
or
> > > > operations
> > > > > > > > faster, and also developers can trace back any OGNL
> expressions
> > > in
> > > > > the
> > > > > > > JSP
> > > > > > > > to it's corresponding Java code.
> > > > > > > >
> > > > > > > > This approach places code in a shareable component.
You can
> > > easily
> > > > > > > > aggregate one JSPHelper into another one, and then
either
> > provide
> > > > > > wrapper
> > > > > > > > methods or simply push the aggregate helper onto the
stack
> > using
> > > > the
> > > > > > > s:push
> > > > > > > > tag for direct access to it's members.
> > > > > > > >
> > > > > > > > This approach makes the actions leaner, and provides
a very
> > clear
> > > > cut
> > > > > > > view.
> > > > > > > > I find at times that the action tends to be both controller
> and
> > > > view,
> > > > > > > when
> > > > > > > > really it should only act as the controller (IMO).
> > > > > > > >
> > > > > > > > This technique is functionally very similar to ModelDriven,
> but
> > > > it's
> > > > > > used
> > > > > > > > slightly differently. I've used a JspHelper in combination
> with
> > > > > > > > ModelDriven, and I've found the JspHelper to be a
good place
> to
> > > > store
> > > > > > > > logic.. and leave the Model strictly as a business
object.
> > > > > > > >
> > > > > > > > *Conclusion
> > > > > > > > *
> > > > > > > > I have personally found this technique incredibly
useful in
> > > > cleaning
> > > > > up
> > > > > > > > code. You can shift all of the JSP exclusive logic
and
> > properties
> > > > to
> > > > > > the
> > > > > > > > helper without touching the JSP (the OGNL expressions
remain
> > the
> > > > > same).
> > > > > > > > Then after that initial step, you have a real handle
on the
> > exact
> > > > > input
> > > > > > > > your JSP needs, and the actual clean up process progresses
> > faster
> > > > and
> > > > > > > with
> > > > > > > > less errors. I'm still in the process of establishing
some
> best
> > > > > > > practices,
> > > > > > > > but so far this approach is working for us.
> > > > > > > >
> > > > > > > > I would like some honest feedback
> > > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > --
> > > > > > > e: davelnewton@gmail.com
> > > > > > > m: 908-380-8699
> > > > > > > s: davelnewton_skype
> > > > > > > t: @dave_newton <https://twitter.com/dave_newton>
> > > > > > > b: Bucky Bits <http://buckybits.blogspot.com/>
> > > > > > > g: davelnewton <https://github.com/davelnewton>
> > > > > > > so: Dave Newton <
> > http://stackoverflow.com/users/438992/dave-newton
> > > >
> > > > > > >
> > > > > >
> > > > >
> > > > >
> > > > >
> > > > > --
> > > > > e: davelnewton@gmail.com
> > > > > m: 908-380-8699
> > > > > s: davelnewton_skype
> > > > > t: @dave_newton <https://twitter.com/dave_newton>
> > > > > b: Bucky Bits <http://buckybits.blogspot.com/>
> > > > > g: davelnewton <https://github.com/davelnewton>
> > > > > so: Dave Newton <http://stackoverflow.com/users/438992/dave-newton
> >
> > > > >
> > > >
> > >
> > >
> > >
> > > --
> > > e: davelnewton@gmail.com
> > > m: 908-380-8699
> > > s: davelnewton_skype
> > > t: @dave_newton <https://twitter.com/dave_newton>
> > > b: Bucky Bits <http://buckybits.blogspot.com/>
> > > g: davelnewton <https://github.com/davelnewton>
> > > so: Dave Newton <http://stackoverflow.com/users/438992/dave-newton>
> > >
> >
>
>
>
> --
> e: davelnewton@gmail.com
> m: 908-380-8699
> s: davelnewton_skype
> t: @dave_newton <https://twitter.com/dave_newton>
> b: Bucky Bits <http://buckybits.blogspot.com/>
> g: davelnewton <https://github.com/davelnewton>
> so: Dave Newton <http://stackoverflow.com/users/438992/dave-newton>
>
|