I'm working on a JSP where I need to call methods on object that come from a Bean. The previous version of the page does not use JSTL and it works properly. My new version has a set up like this:
<jsp:useBean id="pageBean" scope="request" type="com.epicentric.page.website.PageBean" />
<c:set var="pageDividers" value="<%= pageBean.getPageDividers() %>" />
<c:set var="numColumns" value="${pageDividers.size()}" />
The variable pageDividers is a List object.
I'm encountering this issue: when I ask for pageDivider's size, an exception is thrown. I know this is a simple JTSL error -- what am I doing wrong?
The error message is:
The function size must be used with a prefix when a default namespace is not specified
How do I correctly access or call the methods of my pageDividers object?
When using the dot operator for property access in JSTL, ${pageDividers.size} (no () needed) results in a call to a method named getSize().
Since java.util.List offers a method called size() (rather than getSize()) you won't be able to access the list length by using that code.
In order to access to a list size, JSTL offers the fn:length function, used like
${fn:length(pageDividers)}
Note that in order to use the fn namespace, you should declare it as follows
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
In addition, the same function can be used with any collection type, and with Strings too.
To access the property of a bean using EL you simply name the property (not invoke the method). So lets say you have a method called getSize() in the bean then
${pageDividers.size}
Notice no ().
EDIT:Sorry...made an error in the original post.
Related
I have a JSP file that includes another JSP file. The first JSP should pass an instance of a Java class (widget) to the second JSP file.
This is what I have:
The first JSP:
<jsp:include page="/container/SpecialWidget.jsp">
<jsp:param name="widget" value="${widget}"/> // widget is a .Java POJO
</jsp:include>
The second JSP:
${param.widget.id}
The problem is that this code gives an error (it says it doesn't know ID). If I omit the ".id" part, the page prints the Java code for the Java class, which means the class has been transferred correctly. If I change the ${widget} rule of the first page in, for example, ${widget.id} and I try to print ${param.widget}, everything works fine.
My question: Why can't I pass a Java class and directly call upon its attributes? What am I doing wrong?
Edit: error message: Caused by: javax.el.PropertyNotFoundException: Property 'id' not found on type java.lang.String
I managed to fix my problem with the following code:
<c:set var="widget" value="${widget}" scope="request" />
<jsp:include page="/SOMEWHERE/SpecialWidget.jsp"/>
Thank you both for your help:) It saved my day
When you pass the variable ${widget} it is translated at request time to a string (widget.toString()). This value is then passed to the second JSP as a String, not as the original java object.
One approach to access the object's values is setting the parameter's value with the attribute's value:
<jsp:param name="widgetId" value="${widget.id}"/>
Then use the code bellow on the second JSP:
${param.widgetId}
You can also set widget as an request attribute and use it on the second page as ${widget.id} or ${request.widget.id}. I suggest you use the second approach.
<jsp:param> passes the parameter as an HTTP request parameter, which can only be a String. So toString() is called on your widget, and the result of this method is passed as parameter.
You should use a JSP tag, implemented as a tag file, instead of using a JSP include. See http://docs.oracle.com/javaee/1.4/tutorial/doc/JSPTags5.html for how to define an use them.
For example:
Tag definintion, in /WEB-INF/tags/specialWidget.tag:
<%# tag %>
<%# attribute name="widget" required="true" type="the.fully.qualified.name.of.WidgetClass" %>
TODO: add the HTML markup that must be displayed, using ${widget} to access the passed in widget attribute
Tag usage, in any JSP:
<%# taglib prefix="myTags" tagdir="/WEB-INF/tags" %>
...
Tada! I will use the specialWidget tag here, with widget as an attribute:
<myTags:specialWidget widget="${widget}"/>
If I want to get the property from a bean and use it for some Java Code. Such as, get the visitor count but not output it, just for some other use. I cannot use because it'll output the value.
How can get the property but not output it?
You can set property to any variable then you can process it.
<c:set var="name" scope="scope" value="expression"/>
for example :
<c:set var="visitorCount" scope="scope" value="someBean.counter"/>
even you can process it without setting
This example retrieves a session-scoped bean and makes it available using the id myBean. Although it's not a good practice to have scriptlets in your jsp code, but one way is to call any method on the bean as shown below.
<jsp:useBean id="myBean" class="com.mycompany.MyBean" scope="session" />
<% myBean.getprop1(); %>
<jsp:useBean id ="object instance" class="full qualified path of ur class" scope="according to need"/>
<jsp:getProperty name="same as id" property="name of the property"/>
use according to this u must get ur result without using scripting....
I'm using Spring Web Flow (v. 1.0.5) and I have a JSP page that makes an AJAX call to a flow and needs to read in the XML results. That flow successfully sets an object into the FlowScope, then calls a JSP page to render the results. In the JSP page, I'd like to test whether the object has a property (say, .firstName) and if so, do something. I can access the variable in the FlowScope using JSTL expression language (by saying ${userObj}), but that just lets me spit it out. I've tried the methods below to get at it and put logic around it, with varying success.
Update: The remaining question is: How do I get the context and flow scope in the scriptlet (<% %>) section?
<rootnode>
<!-- Attempt 1: c:if isn't being interpreted (though ${userObj.firstName} is),
it's just displaying the tags on the page. -->
<!-- Update, I didn't have the <%# taglib directive for jstl/core.
Now I do, and they're being interpreted, but it says
"According to TLD or attribute directive in tag file,
attribute test does not accept any expressions"
How can the if/#test not accept expressions? Isn't that its whole purpose
in life? -->
<!-- Update 2, I also forgot the taglib for the rt language, which is separate,
I guess (jstl/core_rt). <c:if test now works properly. -->
<c:if test="${!empty(userObj.firstName)}">
<test>not empty</test>
</c:if>
<%
/* Attempt 2: This throws an error, can't resolve "context". How do I get the context? */
if (context.getFlowScope().userObj != null) {
out.write("not null");
} else {
out.write("not not null");
}
%>
<!-- Attempt 3: This works, I get the reference to the Object and it
spits out the correct firstName, gives me no control other than
spitting out the value. -->
<userReference>${userObj}</userReference>
<userReference_firstName>${userObj.firstName}</userReference_firstName>
</rootnode>
Attempt 1 should work if you installed JSTL and declared the taglib the right way and declared the web.xml to be at least Servlet 2.4. Also see the questions:
Where do I put jstl.jar and standard.jar so that Netbeans don't give errors/warnings?
ModelAttributes not accessible on jsp
To test if an object is empty or not, you should rather use the following construct:
<c:if test="${not empty userObj.firstName}">
or
<c:if test="${userObj.firstName != null}">
Attempt 2 is strongly discouraged. Scriptlets are a poor practice and should always be replaced by taglibs like JSTL and EL (as you did in attempt 1). If it's not possible for technical reasons, then the coding ought to be done in a real Java class, (indirectly) starting with a Servlet.
Attempt 3 is doable, but I would recommend to use servlet with a Javabean-to-XML serializer like XStream instead. This way you can just feed a collection of Javabeans to the outputstream of the response transparently.
I'm using JBOSS 4.0.2 with JSP 2.0.
I have created a TAG file with the following directives:
<%# attribute name="id" required="true" %>
<%# attribute name="upgradeAccount" type="com.upc.domain.UpgradeAccountData" %>
However, when I try to pass an object of type UpgradeAccountData to the tag as a parameter it is always resolved as String, for instance :
<wmtags:paymentOptions id="23" upgradeAccount="${upgradeAccountCommand}">
</wmtags:paymentOptions>
in the above example the upgradeAccountCommand is passed as the "${upgradeAccountCommand}" string.( I've check it by defining the the type attribute in the tag as object and printing the object type and it's string value).
I've also made sure that the upgradeAccountCommand in the caller page is an actual UpgradeAccountData object.
What can I do to solve this?
Many Thanks
That should work; it sounds like EL expression evaluation might be turned off? That could be due to <%#page isELIgnored="false"%> in the page, or the webapp is using the 2.3 servlet spec (or earlier).
Try this:
<wmtags:paymentOptions id="23" upgradeAccount="<%=upgradeAccountCommand%>">
So according to my JSP reference book, as well as every other reference I can find on the web, I'm supposed to be able to do something like:
<%# tag dynamic-attributes="dynamicAttributesVar" %>
and then when someone uses an attribute that I didn't define in an attribute directive, I should be able to access that attribute from the "dynamicAttributesVar" map:
<%= dynamicAttributesVar.get("someUnexpectedAttribute") %>
However, that doesn't work, at all; I just get a "dynamicAttributesVar cannot be resolved" error when I try.
Now, I did discover (by looking at the generated Java class for the tag) that I can "hack" a working dynamic attributes variable by doing:
<% Map dynamicAttributesVar = _jspx_dynamic_attrs; %>
Now, that hack doesn't work unless I also use the dynamic-attributes parameter on my tag directive, so it seems that the parameter is doing something.
But what I want to know is, how can I make it do what it does for every other JSP user out there?
Just trying to get a badge for answering a four year old question.
I have this problem as well and came across some help at O'Reilly to use JSTL instead of scriptlets.
The original poster could have used this code to get all keys/values:
<c:forEach items="${dynamicAttributesVar}" var="a">
${a.key}="${a.value}"
</c:forEach>
This would get a specific value:
<c:out value="${dynamicAttributesVar['someUnexpectedAttribute']}"/>
Isn't "dynamicAttributesVar" the name of the key in the page context that the dynamic attributes are put into? So you could do
<c:out value="${dynamicAttributesVar.someUnexpectedAttributes}"/>
or if you must use scriptlets:
Map dynamicAttributes = (Map) pageContext.getAttribute("dynamicAttributesVar")
(Disclaimer: I haven't tried it, I've just used dynamic attributes in tags with direct Java implementations... but it seems reasonable)