Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / January 2008

Tip: Looking for answers? Try searching our database.

problem upgrading to JSTL 1.2

Thread view: 
yishayjobs@hotmail.com - 23 Dec 2007 13:04 GMT
Hi All,

We in the process of upgrading our JBoss implementation from version
4.0.3 to 4.2.2. This also implies moving from JSTL 1.1 to JSTL 1.2 and
from Tomcat 5 to Tomcat 6.

Now some of our old JSPs don't work.

For example:

<%-- ${currGroup.current.value} is an ArrayList --%>
<c:set var="messageList" value="${currGroup.current.value.list}"/>

throws the following exception:

javax.el.PropertyNotFoundException: Property 'list' not readable on
type java.util.List

I've found out that changing
${currGroup.current.value.list}
to
#{currGroup.current.value.list} fixes this problem. But I wouldn't
want to make this change all across our JSPs. Besides I thought JSTL
1.2 was supposed to be backwards compatible to JSTL 1.1. That's what
it says here:

http://today.java.net/pub/a/today/2006/03/07/unified-jsp-jsf-expression-language
.html#backwards-compatibility


Does anyone have an explanation?

Cheers,
Yishay
Lew - 23 Dec 2007 17:35 GMT
> Hi All,
>
[quoted text clipped - 25 lines]
>
> Does anyone have an explanation?

I might, after seeing the definition of the backing bean, particularly the
currGroup object's type, and the declaration of getCurrent(), its type, its
declaration of getValue(), its type in turn, and the declaration of that
type's getList().  The error message indicates that getValue() already returns
a java.util.List(), which of course would not itself have a getList() method.

Incomplete examples lead to incomplete answers.

Signature

Lew

yishayjobs@hotmail.com - 24 Dec 2007 18:14 GMT
> yishayj...@hotmail.com wrote:
> > Hi All,
[quoted text clipped - 39 lines]
>
> - Show quoted text -

Thanks for your quick answer. I'll try to add the missing background.
The expression is read from within a forEach loop in the following
manner:

<c:forEach items="${messageGroup}" varStatus="currGroup">
 <c:set var="messageList" value="${currGroup.current.value.list}"/>
 <%-- this is irrelevant as it never reaches this spot -->
</c:forEach>

messageGroup is a Map<org.apache.struts.action.GLOBAL_MESSAGE,
org.apache.struts.action.ActionMessages.ActionMessageItem>

So the map is iterated over, currGroup.current.value means
org.apache.struts.action.ActionMessages.ActionMessageItem is accessed,
and currGroup.current.value.list would mean
org.apache.struts.action.ActionMessages.ActionMessageItem.getList() is
called. This method does exist, as I've verified in my java code. It's
also part of the API, as explained in

http://struts.apache.org/1.x/struts-core/apidocs/org/apache/struts/action/Action
Messages.ActionMessageItem.html#getList
()

------

Perhaps now you can understand my question. Why does this work:

<c:set var="messageList" value="#{currGroup.current.value.list}"/>

while this doesn't?

<c:set var="messageList" value="${currGroup.current.value.list}"/>
Lew - 24 Dec 2007 18:51 GMT
>> yishayj...@hotmail.com wrote:
>>> Hi All,
[quoted text clipped - 60 lines]
>
> <c:set var="messageList" value="${currGroup.current.value.list}"/>

The c:forEach attribute varStatus is of type
javax.servlet.jsp.jstl.core.LoopTagStatus.

That, in turn, has method getCurrent() that returns Object, which does not
have a getValue() method.

But maybe somehow one environment magically figured out the Object is really a
Map.Entry, so it let you get away with it.  It shouldn't have.

So your Entry getValue() returns an ActionMessageItem.  That in term has a
getList().  Gotcha.

But the error message you reported says, "javax.el.PropertyNotFoundException:
Property 'list' not readable on type java.util.List".  That implies that the
parser is trying to read "value" as a List already.  Just out of curiosity,
would it work with just

 <c:set var="messageList" value="${currGroup.current.value}" />
?

I think I'd rather use a request or page variable 'values' retrieved from
messageGroup.values(), and

 <c:forEach items="${values} var="item" >
   <c:set var="messageList" value="${item.list}" />
   ...
 </c:forEach>

Let us know the answer to my question above.

Signature

Lew

yishayjobs@hotmail.com - 25 Dec 2007 15:56 GMT
> yishayj...@hotmail.com wrote:
> >> yishayj...@hotmail.com wrote:
[quoted text clipped - 96 lines]
>
> - Show quoted text -

> parser is trying to read "value" as a List already.  Just out of curiosity,
> would it work with just
>
>   <c:set var="messageList" value="${currGroup.current.value}" />
> ?

Yes, that does work.

As for my own question:

> > Perhaps now you can understand my question. Why does this work:
>
[quoted text clipped - 3 lines]
>
> > <c:set var="messageList" value="${currGroup.current.value.list}"/>

I was not correct to say the first instance works; I think it is just
evaluated as a literal, which avoids the exception but still means a
malfunction. I'll have to inspect the variables more closely and see
why java.Util.List is ever accessed.
Lew - 25 Dec 2007 18:31 GMT
> I was not correct to say the first instance works; I think it is just
> evaluated as a literal, which avoids the exception but still means a
> malfunction. I'll have to inspect the variables more closely and see
> why java.Util.List is ever accessed.

java.util.List, surely.

Signature

Lew

yishayjobs@hotmail.com - 30 Dec 2007 15:41 GMT
> yishayj...@hotmail.com wrote:
> > I was not correct to say the first instance works; I think it is just
[quoted text clipped - 6 lines]
> --
> Lew

The following jsp (I named it 'master.jsp') is as simple as I've
gotten it.

=====

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="org.apache.struts.action.ActionMessage"%>
<%@ page import="org.apache.struts.action.ActionMessages"%>

<%! public class MyActionMessages extends ActionMessages {
       public java.util.Map getMessages() {
           return messages;
       }
}
%>

<%
    MyActionMessages actionMessages = new MyActionMessages();
           actionMessages.add("prop1", new ActionMessage("one"));
           session.setAttribute("my_action_message_item",
actionMessages.getMessages().get("prop1"));
%>
<html>
<body>
<span>this is a test: ${my_action_message_item.list}</span><br>
</body>
</html>

====

The message I get is:

org.apache.jasper.JasperException: An exception occurred processing
JSP page /views/profiler/master.jsp at line 20

...

root cause

javax.el.PropertyNotFoundException: Property 'list' not readable on
type java.util.List
    javax.el.BeanELResolver$BeanProperty.read(BeanELResolver.java:259)
    javax.el.BeanELResolver$BeanProperty.access$000(BeanELResolver.java:
209)
    javax.el.BeanELResolver.getValue(BeanELResolver.java:60)
    javax.el.CompositeELResolver.getValue(CompositeELResolver.java:53)
    org.apache.el.parser.AstValue.getValue(AstValue.java:97)
    org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:
186)
   
org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:
923)
    org.apache.jsp.views.profiler.master_jsp._jspService(master_jsp.java:
77)

==========

This is after the upgrade (see my opening post). Before upgrade the
list is evaluated in the normal toString fasion. I get:

====

this is a test: [one[]]

====

It might be be struts or jstl, I'm not sure. It also might be bad
coding on our side, but as I've mentioned this is not my worry. My
worry is performing the upgrade with minimal cost, given our perhaps
badly written legacy code.
Lew - 30 Dec 2007 16:26 GMT
> The following jsp (I named it 'master.jsp') is as simple as I've
> gotten it.
[quoted text clipped - 59 lines]
>
> this is a test: [one[]]

The object retrieved via 'my_action_message_item' is the one from the call to
> actionMessages.getMessages().get("prop1")

'actionMessages.getMessages()' is a Map, 'messages'.  A raw Map.
'messages.get("prop1")' returns an Object.  'Object' does not have a method
'getList()'.  Boom.  But that's not the error.  Somehow the system figured out
what the underlying Map types are.  Let's follow that chain.

The retrieval from getMessages() is the protected 'messages' element of the
superclass, a HashMap that maps String to an ArrayList.  So the result of
get("prop1") is an ArrayList<ActionMessage>.

You then call getList() on that ArrayList.  But ArrayList doesn't have such a
method.  Now boom.

The exception is correct behavior.

Signature

Lew

yishayjobs@hotmail.com - 31 Dec 2007 09:56 GMT
> yishayj...@hotmail.com wrote:
> > The following jsp (I named it 'master.jsp') is as simple as I've
[quoted text clipped - 83 lines]
>
> - Show quoted text -

Is the result of get("prop1") an ArrayList? API docs support this

http://struts.apache.org/1.2.4/api/org/apache/struts/action/ActionMessages.html#
messages


But if you run the following jsp (you're welcome to try it; it's self
contained):

-----------
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="org.apache.struts.action.ActionMessage"%>
<%@ page import="org.apache.struts.action.ActionMessages"%>

<%! public class MyActionMessages extends ActionMessages {
       public java.util.Map getMessages() {
           return messages;
       }
}
%>

<%
    MyActionMessages actionMessages = new MyActionMessages();
           actionMessages.add("prop1", new ActionMessage("one"));
           Object myObject = actionMessages.getMessages().get("prop1");
           session.setAttribute("is_list", new Boolean (myObject
instanceof java.util.List));
           session.setAttribute("my_action_message_item", myObject);
%>
<html>
<body>
<span>is list? ${is_list}</span><br>
<span>class name: ${my_action_message_item.class.name}</span><br>
</body>
</html>
---------

You'll get:

---------

is list? false
class name: org.apache.struts.action.ActionMessages$ActionMessageItem

---------
Lew - 31 Dec 2007 15:45 GMT
>> yishayj...@hotmail.com wrote:
>>> The following jsp (I named it 'master.jsp') is as simple as I've
[quoted text clipped - 110 lines]
>
> ---------

What is your point here?  You've proven that Java cannot decipher the
underlying type the way your container seems to be able to.

The return value of get("prop1") from your custom class is an Object, not a
java.util.List.  The results you show are correct.

> 'actionMessages.getMessages()' is a Map, 'messages'.  A raw Map.
> 'messages.get("prop1")' returns an Object.

*Not* a List.

So the result 'false' is correct.

What's amazing to me is that the container figured out that the object is a
List even though your code does its level best to hide that fact.  It should
have crashed before then.

Signature

Lew

yishayjobs@hotmail.com - 06 Jan 2008 12:47 GMT
> yishayj...@hotmail.com wrote:
> >> yishayj...@hotmail.com wrote:
[quoted text clipped - 133 lines]
>
> - Show quoted text -

If the container figure out the object is a list then why does

-------
<span>class name: ${my_action_message_item.class.name}</span><br>
-------

result in

-------
class name: org.apache.struts.action.ActionMessages$ActionMessageItem
-------

?
Lew - 30 Dec 2007 16:37 GMT
>> yishayj...@hotmail.com wrote:
>>> I was not correct to say the first instance works; I think it is just
[quoted text clipped - 33 lines]
> </body>
> </html>

Why aren't you simply using <bean:message>?
<http://struts.apache.org/1.x/struts-taglib/tlddoc/bean/message.html>

<bean:message key="prop1" />

Signature

Lew



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.