IlleagalStateException when wrapping spring mvc se

2019-08-30 17:11发布

问题:

Basic problem
I've come across a bit of a problem while writing my own custom JSP tags to "wrap" the spring MVC form tags. I've wrapped other tags successfully but come unstuck with the select and options tags, this throws an IlleagalStateException. I've debugged the spring code and found that the options tag looks for an ancestor select tag. I'm doing this with tag files so the spring select tag is actually in a different tag file. I guess that's why it doesn't find it.

So the questions is what can I do to get round this?

Possible solutions
I've tried looking for solutions but all I've found is other people having the same problem but no solution posted. I did ponder writing my own select and options tags without using the spring tags but I don't really want to have to replicate the binding that it gives you for free. I don't mind changing to use Java classes rather than tag files but I found previously that the output won't be evaluated as a JSP so you can't output another JSP tag.

Reasons for doing this
Having thought about this for a week since first asking the question I am now clearer on what I want to achieve.

  • To simplify the markup needed in my JSP's
  • Factoring out common code (e.g. form:errors after an input or getting a translation from spring:message)
  • To encapsulate look and feel (CSS goes a long way but often you need to change the markup too)
  • To be able to build enhanced components that extend the functionallity of the spring tags (e.g. render a multi-select as a picklist or display readonly inputs as text labels)

I'll be interested to hear what people think. Thanks

回答1:

Firstly, I'm not sure what you mean by wanting control over styling. I thought you could pass-in class and id attributes to Spring tags and they were copied through (? - although I might be getting confused with Grail tags, as I've been writing Grails apps lately). Edit: plus you can style Spring generated tags by referencing an outer element. E.g. surround your form elements with a div and then style the form elements like: #myDiv input { color: red; }.

From my experience (10+ years webapp dev), its not worth the extra effort to try and future proof your app. When you choose a framework like Spring MVC you are getting a lot of stuff for free, that you would normally have to write yourself. The cost of this free stuff is a certain amount of lock-in (as you said). Spring is pretty good when it comes to this aspect - you can use as little or as much as you want and its usually pretty straight forward to engineer it out if needs be in the future.

So my take is: use the Spring tags "as is". The likelihood of you needing to remove the Spring aspect in the future is very small. As such its a worthwhile risk to "put off" if/until that scenario arrises. You have likely already spent as much time and code trying to engineer your future-proof solution as you would've spent removing the Spring tags - that it outweighs any benefit it might have provided. And add to that - you've written that code and you and/or someone else will have to maintain that code now - versus letting the Spring developers maintain the code for you.

Lastly, if you really don't want to have this lock-in and want full control over styling, then write your form elements by hand.

<select name="foo_select">
    <option value="">-- select a foo type --</option>
    <c:forEach var="foo" items="${fooGroups}">
        <option value="${foo}">${foo}</option>
    </c:forEach>
</select>


回答2:

I've thought about this for a good week now and this is the shortlist:

  • Give up and directly use the spring tags in my JSP's
  • Don't use the spring tags at all and replicate their logic in my own tags
  • Possibly write a tag class that extends or makes use of the spring tag class
  • Expand the scope of my tags to wrap both the select and options tags

Given the reasons for wanting to do this (which I have now clarified in the question), I've decided to go for the last option. I wasn't keen on this originally because I thought I might end up with hundreds of parameters but it's actually not too bad. The tag files are designed for wrapping common bits of markup so this is what they're for. I've also wrapped my own tag further so there is a picklist tag which outputs my custom select tag and then writes the JS needed to initialise it.

I think this is the best of the possible solutions I've come across based on what I wanted to achieve. This is what I'm going with but I'd still be interested to hear of other peoples solutions if they think they have something better.