Nathan Andelin skrev den 06-07-2008 00:08:
Thorbjørn Ravn Andersen wrote:
But for presentation purposes Maps do nicely :)
I actually wanted to bring this up at some point, Thorbjørn. I assumed
that the reason for mapping SQL result sets to objects had something to
do with implementing business rules and procedures. And I asked Sarah
about that. But I also wanted to find out about the next step, which is
mapping objects to whatever is streamed to the browser. And your
message implies that objects are mapped to JSF components. Would you
care to elaborate? Is the mapping automatic, for example?
I can give it a try.
(While brushing up on this I found some good links you might be
interested in:
Get something working:
http://www.exadel.com/web/portal/tutorials
An overview over tags:
http://www.horstmann.com/corejsf/jsf-tags.html
)
Normally in JSP to display a value you do something like <%=
foo.getBar() %> which is directly mapped by thSee JSP compiler to
something like "System.out.print(foo.getBar())". You then must have a
"foo" object in scope to refer to, which in turn must have a bar getter
to call. If not, you will get an error.
There is nothing wrong with having a map in scope and print out values
from it with e.g <%= map.get("Name") %>. Most documentation just talk
about POJO's (plain old java objects) with getters and setters, which
most likely is to enforce new learners to think statically typed but as
always there is more than one way to do it.
In JSF there are several scopes - application, session, request (plus
some more) - which refer to how long JSF holds on to them. See
http://www.java-samples.com/showtutorial.php?tutorialid=472
For presentation purposes the request scope is perfect. Let us look at
a case where the user selects a link to display a table of names. This
looks like
<h:commandLink id="link" action="#{F.goB}" value="go" />
where F is defined in faces-config.xml as
<managed-bean>
<managed-bean-name>F</managed-bean-name>
<managed-bean-class>test.F</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
(note that the class is also named F, helps a LOT) and the test.F class
looks like
==
package test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class F {
List l = new ArrayList();
public F() {
System.out.println("F " + new java.util.Date());
}
public String goA() {
System.out.println("goA()");
HashMap map = new HashMap();
map.put("name", "Alice");
map.put("place", "Living room");
l.add(map);
map = new HashMap();
map.put("name", "Bob");
map.put("place", "Next door");
l.add(map);
return "b";
}
public String goB() {
System.out.println("goB()");
HashMap map = new HashMap();
map.put("name", "Bob");
map.put("place", "Home");
l.add(map);
map = new HashMap();
map.put("name", "Christine");
map.put("place", "The Opera");
l.add(map);
return "a";
}
public List getL() {
System.out.println("F.l = " + l);
return l;
}
}
==
The link will call F.goB() which prepares the field l as an arraylist
with two map elements (the return value b is used to navigate to the
presentation page b.jsp)
b.jsp looks like:
==
<%@ page language="java" pageEncoding="ISO-8859-1"%>
<%@ taglib uri="
http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="
http://java.sun.com/jsf/core" prefix="f"%>
<html>
<body>
<f:view>
Page B<h:form id="foob">
<h:commandLink id="link" action="#{F.goB}" value="go" />
</h:form>
<h:dataTable border="1" var="i" value="#{F.l}"
rendered="#{not empty F.l}">
<h:column>
<f:facet name="header"><h:outputText value="Name"
/></f:facet>
<h:outputText value="#{i.name}" />
</h:column>
<h:column>
<f:facet name="header"><h:outputText value="Place"
/></f:facet>
<h:outputText value="#{i.place}" />
</h:column>
</h:dataTable>
</f:view>
</body>
</html>
==
Note there is a link back to a.jsp (which renders the table in another
way), and the h:dataTable presents the list in F.l with each item in it
as a row. BUT the table is not rendered at ALL unless "not empty F.l"
is true. So no table unless there is anything to show.
var="i" binds the variable i to the current item in the list, and
"i.name" and "i.place" expressions look "name" and "place" up in the map
directly, so it is just outputting them in the appropriate column. The
same syntax had been used if the list had consisted of POJO's with
getName() and getPlace(). That is pretty nifty.
The result looks like
Name Place
Alice Living room
Bob Next door
So, it _is_ very simple when you get all the JSF-scaffolding up and
running correctly (sigh).
====================================================================
I created a small sample project in MyEclipse which I have zipped and
attached for those curious. It contains the above mentioned jsp files
for those without MyEclipse.
(To load project into MyEclipse)
Save the attached map.zip
Start MyEclipse
File->Import->General->Existing Projects into Workspace
Select "Select archive file" and browse to the map.zip saved above
In the Projects panel, the "map" project should appear and be checked.
Click "Finish"
(Setup deployment)
Click button in toolbar with the tooltip "Deploy MyEclipse J2EE Project
to Server..." (two black things with arrows between)
Ensure that "map" is the selected project
Click "Add"
In "Server" select "MyEclipse Tomcat"
Ensure that the Deploy Type is Exploded Archive
Click "Finish"
Click "Ok" to close the remaining dialogue box.
(Start server)
Click dropdown arrow next to button in toolbar with the tooltip
"Run/Stop/Restart MyEclipse Servers..." (computer with green arrow in front)
Select "MyEclipse Tomcat Server" -> "Start"
(Start browser)
Open a browser to "
http://localhost:8080/map"
You should _see_ the contents of a.jsp as rendered by JSF.
Try clicking around and see what happens...
Hope this helps some :)
As an Amazon Associate we earn from qualifying purchases.