I have a JSF page where I want to show a image. The image is stored in the database as a blob.
The entity looks like this:
#Entity
public class Player
{
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private Long id;
#Lob
private byte[] pictureData;
#Transient
private StreamedContent streamedPicture;
public StreamedContent getStreamedPicture()
{
if (streamedPicture == null && pictureData != null)
{
try
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
os.write(pictureData);
streamedPicture = new DefaultStreamedContent(
new ByteArrayInputStream(
os.toByteArray()),
"image/png");
}
catch (FileNotFoundException e)
{}
catch (IOException e)
{}
}
return streamedPicture;
}
}
The JSF page is this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<body>
<ui:repeat var="player" value="#{playerbean.cachedPlayers}">
<h:outputText value="#{player.id}" />
<p:graphicImage value="#{player.streamedPicture}" rendered="#{player.streamedPicture != null}"/>
</ui:repeat>
</body>
</html>
And the bean I call looks like this:
#ManagedBean(name = "playerbean")
#SessionScoped
public class PlayerBean
implements Serializable
{
#EJB
private PlayerManager playerManager;
private List<Player> cachedPlayers;
public List<Player> getCachedPlayers()
{
if (cachedPlayers == null)
{
cachedPlayers = playerManager.getAll();
}
return cachedPlayers;
}
}
While debugging I set a breakpoint in PrimeResourceHandler in the method handleResourceRequest(). The code of the PrimeResourceHandler I'm looking at contains this:
try {
String dynamicContentEL = (String) session.get(dynamicContentId);
ELContext eLContext = context.getELContext();
ValueExpression ve = context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(), dynamicContentEL, StreamedContent.class);
StreamedContent content = (StreamedContent) ve.getValue(eLContext);
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
response.setContentType(content.getContentType());
byte[] buffer = new byte[2048];
int length;
InputStream inputStream = content.getStream();
while ((length = (inputStream.read(buffer))) >= 0) {
response.getOutputStream().write(buffer, 0, length);
}
response.setStatus(200);
response.getOutputStream().flush();
context.responseComplete();
} catch(Exception e) {
logger.log(Level.SEVERE, "Error in streaming dynamic resource.");
} finally {
session.remove(dynamicContentId);
}
When passing the line StreamedContent content = (StreamedContent) ve.getValue(eLContext); content appears to be null. This of course causes a NullPointerException. However in the JSF page I told the element not to render if the value is null.
The <p:graphicImage> component cannot have a value attribute that points to a managed property within a SessionScoped bean. The value must be set to a RequestScoped bean.
This is because an HTTP request for an image/jpeg content type HTTP response is inherently stateless. The browser will make the initial request for the JSF page content, then for every HTML <img> tag that is rendered it will make seperate requests to the dynamically generated url of each <img> tag to fetch these. Fetching an image in a stateful context doesn't really make sense.
Related
i have a simple file.xhtml in a JSF2.2 application, that's its code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ez="http://xmlns.jcp.org/jsf/composite/ezcomp">
<head>
<title>Insert title here</title>
</head>
<body>
<f:view>
<h:form id="greeting">
<h:inputText id="num1" value="#{jSFeatBean.num1}" />
<h:inputText id="num2" value="#{jSFeatBean.num2}"/>
<h:commandButton type="submit"
value="Submit"
action="#{jSFeatBean.addNumbers()}"/>
<h:outputText value="#{jSFeatBean.result}"/>!
</h:form>
</f:view>
</body>
</html>
and this is my #ManagedBean:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name = "jSFeatBean", eager = true)
#SessionScoped
public class JSFeatursBean {
private String result;
public int num1 = 1;
int num2;
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public Object addNumbers() {
setResult("il risultato e': "+ Integer.toString(num1+num2));
return null;
}
}
after i start jboss from Eclipse the browser display all elements of my file.xhtml properly but the values in the first (id = num1) inputText is 0 and not 1. Why this happens? If i put new values in the inputText boxes everything works fine, so i think that the Mbean is instantiated and working.
I have the same problem with a h:SelectOneListbox element, that doesn't show the list i create when i call the MBean constructor.
It looks like the MBean gets instatiated right after the display of html page.
The code looks fine to me with just one thing that might cause the problem.
Try remove "eager = true" attribute in your ManagedBean annotation. "eager = true" only works with ApplicationScoped Beans.
i found a solution in stackoverflow how to code a login in JSF using HttpServletRequest.
First things first, the login.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Login</title>
</h:head>
<h:body>
<h3>Login here</h3>
<h:form id="loginForm">
<h:outputLabel for="username" value="Username:" />
<h:inputText value="#{loginService.userName}" id="username" requried="true" />
<br/>
<h:outputLabel for="password" value="Password:" />
<h:inputSecret value="#{loginService.password}" id="password" requried="true" />
<br/>
<h:commandButton id="button" value="Login" action="#{loginService.doLogin}" />
<br/>
<h:commandLink action="#{navigationService.redirectToIndex}" value="Home" />
<br/>
<h:messages />
<br/>
</h:form>
</h:body>
The loginService:
#Named
#SessionScoped
public class LoginService implements Serializable {
private String userName = "";
private String password = "";
#Inject
private NavigationService navigationService = null;
#Inject
private String originalURL = "";
/**
*
*/
#PostConstruct
public void init() {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
this.originalURL = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI);
if(this.originalURL == null) {
this.originalURL = externalContext.getRequestContextPath() + navigationService.toIndex();
} else {
String originalQuery = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_QUERY_STRING);
if(originalQuery != null) {
this.originalURL += "?" + originalQuery;
}
}
}
/**
*
* #return
* #throws IOException
*/
public void doLogin() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
HttpServletRequest request = (HttpServletRequest)externalContext.getRequest();
try {
request.login(this.userName, this.password);
User user = dao.findUserByUserName(userName);
externalContext.getSessionMap().put("user", user);
externalContext.redirect(this.originalURL);
} catch(ServletException e) {
context.addMessage(null, new FacesMessage("Unknown login"));
} catch (NoSuchUserException e) {
context.addMessage(null, new FacesMessage(e.getMessage()));
}
}
/**
*
* #return
* #throws IOException
*/
public void doLogout() throws IOException {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
externalContext.invalidateSession();
externalContext.redirect(externalContext.getRequestContextPath() + navigationService.toLogin());
}
// Getters and Setters
}
The only thing i still need to know is now:
Where can i define for which pages login is needed?
A suggested solution is: putting all the pages requiring logging under one place (folder, ex: "private_section"), and the pages that don't need it (public access) are to be put wherever in the project context except under the folder "private_section". Then you can use a simple filter to control accessing to the private region (to our folder), and through this pattern (first annotation) you can specify the region to be controlled :
// imports
#WebFilter("/private_section/*")
public class LoggingFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = (HttpServletResponse)response;
UserBean user = (UserBean) req.getSession().getAttribute("user");
if (user != null && user.isLoggedIn()){
chain.doFilter(request,response);
}
else res.sendRedirect(req.getContextPath()+"/index.xhtml");
}
// other overriden methods
I have an issue in my application using where I have a Captcha component built as a JSF Custom Tag:
in my JavaEE 6 webapp I use:
JSF 2.1 + Jboss Richfaces 4.2.3 + EJB 3.1 + JPA 2.0 + PrettyFaces 3.3.3
I have a JSF2 custom tag that is:
<tag>
<tag-name>captcha</tag-name>
<source>tags/captcha.xhtml</source>
</tag>
in my XHTML page called accountEdit.xhtml I have the captcha being displayed:
<ui:fragment rendered="#{customerMB.screenComponent.pageName eq 'create'}">
<div class="form_row">
<label class="contact"><strong>#{msg.captcha}:</strong>
</label>
<atl:captcha></atl:captcha>
</div>
</ui:fragment>
in captcha.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<table border="0">
<tr>
<td>
<h:graphicImage id="capImg" value="#{facesContext.externalContext.requestContextPath}/../captcha.jpg" />
</td>
<td><a4j:commandButton id="resetCaptcha" value="#{msg.changeImage}" immediate="true" action="#{userMB.resetCaptcha}" >
<a4j:ajax render="capImg" execute="#this" />
</a4j:commandButton></td>
</tr>
<tr>
<td><h:inputText value="#{userMB.captchaComponent.captchaInputText}" /></td>
</tr>
</table>
</ui:composition>
in my web.xml I have configured a CaptchaServlet that handles the request for generating a captcha during runtime:
<servlet>
<servlet-name>CaptchaServlet</servlet-name>
<servlet-class>com.myapp.web.common.servlet.CaptchaServlet</servlet-class>
<init-param>
<description>passing height</description>
<param-name>height</param-name>
<param-value>30</param-value>
</init-param>
<init-param>
<description>passing width</description>
<param-name>width</param-name>
<param-value>120</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CaptchaServlet</servlet-name>
<url-pattern>/captcha.jpg</url-pattern>
</servlet-mapping>
My CaptchaServlet implementation:
public class CaptchaServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 6105436133454099605L;
private int height = 0;
private int width = 0;
public static final String CAPTCHA_KEY = "captcha_key_name";
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
height = Integer
.parseInt(getServletConfig().getInitParameter("height"));
width = Integer.parseInt(getServletConfig().getInitParameter("width"));
}
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse response)
throws IOException, ServletException {
// Expire response
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Max-Age", 0);
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = image.createGraphics();
Hashtable<TextAttribute, Object> map = new Hashtable<TextAttribute, Object>();
Random r = new Random();
String token = Long.toString(Math.abs(r.nextLong()), 36);
String ch = token.substring(0, 6);
Color c = new Color(0.6662f, 0.4569f, 0.3232f);
GradientPaint gp = new GradientPaint(30, 30, c, 15, 25, Color.white,
true);
graphics2D.setPaint(gp);
Font font = new Font("Verdana", Font.CENTER_BASELINE, 26);
graphics2D.setFont(font);
graphics2D.drawString(ch, 2, 20);
graphics2D.dispose();
HttpSession session = req.getSession(true);
session.setAttribute(CAPTCHA_KEY, ch);
OutputStream outputStream = response.getOutputStream();
ImageIO.write(image, "jpeg", outputStream);
outputStream.close();
}
}
When I run this app on Glassfish 3.1.1
when the Servlet's doGet() method is called while rendering
for the HttpServlet doGet() method that renders:
<h:graphicImage id="capImg" value="#{facesContext.externalContext.requestContextPath}/../captcha.jpg" />
doGet() renders only once for Google Chrome, thus rendering correctly.
For Firefox and IE doGet() renders twice updating the Captcha Key but not updating the painted Captcha Image on the page.
If anyone might know what could be a fix for this and why it has this behavior for Chrome different from other browsers please let me.
Thanks in advance!
The browser is caching the response. Your attempt to avoid this is incomplete and incorrect:
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Max-Age", 0);
Please refer How to control web page caching, across all browsers? for the proper set:
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
Further, to make it more robust, add a query string with the current timestamp in millis to the image URL. Here's an example provided that you've a java.util.Date instance as managed bean with the name now:
<h:graphicImage id="capImg" value="#{request.contextPath}/../captcha.jpg?#{now.time}" />
(please note that I also simplified the way to get the request context path, I only don't understand how it's useful if you go to domain root by ../ anyway)
I found a solution for this, is not the optimal solution but it works, here it goes:
captcha.xhtml
<table border="0">
<tr>
<td>
<h:graphicImage url="#{request.contextPath}/../jcaptcha"/>
</td>
<td>
<input type='text' name='j_captcha_response' value='' />
</td>
</tr>
</table>
CaptchaServlet doGet method:
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
byte[] captchaChallengeAsJpeg = null;
// the output stream to render the captcha image as jpeg into
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
try {
// get the session id that will identify the generated captcha.
//the same id must be used to validate the response, the session id is a good candidate!
String captchaId = httpServletRequest.getSession().getId();
// call the ImageCaptchaService getChallenge method
BufferedImage challenge =
CaptchaServiceSingleton.getImageChallengeForID(captchaId,
httpServletRequest.getLocale());
// a jpeg encoder
JPEGImageEncoder jpegEncoder =
JPEGCodec.createJPEGEncoder(jpegOutputStream);
jpegEncoder.encode(challenge);
} catch (IllegalArgumentException e) {
httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
} catch (CaptchaServiceException e) {
httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
// flush it in the response
httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.setContentType("image/jpeg");
ServletOutputStream responseOutputStream =
httpServletResponse.getOutputStream();
responseOutputStream.write(captchaChallengeAsJpeg);
responseOutputStream.flush();
responseOutputStream.close();
}
created CaptchaServiceRequestSingleton.java
package com.myapp.web.common.listener;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Locale;
import com.octo.captcha.service.image.DefaultManageableImageCaptchaService;
import com.octo.captcha.service.image.ImageCaptchaService;
public class CaptchaServiceSingleton {
private static ImageCaptchaService instance = new DefaultManageableImageCaptchaService();
private static final int MAX_CACHE_SIZE = 200;
private static HashMap<String, BufferedImage> captchaImgCache = new HashMap<String, BufferedImage>();
public static ImageCaptchaService getInstance(){
return instance;
}
public static BufferedImage getImageChallengeForID(String id, Locale locale) {
if (captchaImgCache.containsKey(id)) {
return captchaImgCache.get(id);
} else {
BufferedImage bImage = instance.getImageChallengeForID(id, locale);
// if limit reached reset captcha cache
if (captchaImgCache.size() > MAX_CACHE_SIZE) {
captchaImgCache = new HashMap<String, BufferedImage>();
}
captchaImgCache.put(id, bImage);
return bImage;
}
}
public static void resetImageChallengeForID(String id) {
if (captchaImgCache.containsKey(id)) {
captchaImgCache.remove(id);
}
}
}
when clicking on "Create Account" button Captcha is reset:
CustomerMB.openCreateCustomerAccount():
public String openCreateCustomerAccount() {
customerAccountEditVO = new CustomerAccountVO();
screenComponent.setPageName(NameConstants.CREATE);
getUserMB().resetCaptcha();
return null;
}
in UserMB.resetCaptcha():
public String resetCaptcha() {
CaptchaServiceSingleton.resetImageChallengeForID(JSFUtil.getRequest().getRequestedSessionId());
return null;
}
Perhaps it's not the perfect solution but at least it's working for all Browsers.
In our JavaEE6 project (EJB3, JSF2) on JBoss 7.1.1, it seems we have a memory leak with SeamFaces #ViewScoped.
We made a little prototype to check the fact :
we use JMeter to call a page 200 times;
the page contains and calls a viewscoped bean which injects a stateful EJB;
we fix the session timeout at 1 minute.
At the end of the test, we check the content of the memory with VisualVM, and here what we got:
with a #ViewScoped bean, we still get 200 instances of the stateful MyController - and the #PreDestroy method is never called;
with a #ConversationScoped bean, #preDestroy method is called a the session end and then we got a clean memory.
Do we badly use the view scope, or is it truly a bug?
Here's the XHTML page:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:s="http://jboss.org/seam/faces">
<f:metadata>
<f:viewParam name="u" value="#{myBean.uselessParam}" />
<s:viewAction action="#{myBean.callService}" />
</f:metadata>
<h:body >
<f:view>
</f:view>
</h:body>
</html>
Now the included bean myBean. For the #ConversationScoped variant, all commented parts are uncommented.
#ViewScoped
// #ConversationScoped
#Named
public class MyBean implements Serializable
{
#Inject
MyController myController;
//#Inject
//Conversation conversation;
private String uselessParam;
public void callService()
{
//if(conversation.isTransient())
//{
// conversation.begin();
//}
myController.call();
}
public String getUselessParam()
{
return uselessParam;
}
public void setUselessParam(String uselessParam)
{
this.uselessParam = uselessParam;
}
}
And then the injected stateful bean MyController:
#Stateful
#LocalBean
public class MyController
{
public void call()
{
System.out.println("call ");
}
#PreDestroy
public void destroy()
{
System.out.println("Destroy");
}
}
I see many developers are satisfied with #ViewAccessScoped in Myface CODI.
Could you please give it a try and tell the feedback.
I have faced the above mentioned problem in JSF managed #ViewScoped bean. After referring to few blogs I understood that JSF saves view bean states in http session and gets destroyed only when session is invalidated. Whenever we click on the jsf page every time new view scope bean referred in page is created. I did a work around using Spring Custom View Scope. It works fine. Below is the detail code.
For JSF 2.1:
Step 1: Create a View Scope Bean Post Construct Listener as follows.
public class ViewScopeBeanConstructListener implements ViewMapListener {
#SuppressWarnings("unchecked")
#Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
if (event instanceof PostConstructViewMapEvent) {
PostConstructViewMapEvent viewMapEvent = (PostConstructViewMapEvent) event;
UIViewRoot viewRoot = (UIViewRoot) viewMapEvent.getComponent();
List<Map<String, Object>> activeViews = (List<Map<String, Object>>)
FacesContext.getCurrentInstance().getExternalContext().getSessionMap(). get("com.org.jsf.activeViewMaps");
if (activeViews == null) {
activeViews = new ArrayList<Map<String, Object>>();
activeViews.add(viewRoot.getViewMap());
FacesContext.getCurrentInstance().getExternalContext().getSessionMap(). put("com.org.jsf.activeViewMaps", activeViews);
} else {
activeViews.add(viewRoot.getViewMap());
}
}
}
Step 2: Register event listener in faces-config.xml
<system-event-listener>
<system-event-listener-class>
com.org.framework.custom.scope.ViewScopeBeanConstructListener
</system-event-listener-class>
<system-event-class>javax.faces.event.PostConstructViewMapEvent</system-event-class>
<source-class>javax.faces.component.UIViewRoot</source-class>
</system-event-listener>
Step 3: Create a Custom View Scope bean as follows.
public class ViewScope implements Scope {
#Override
public Object get(String name, ObjectFactory objectFactory) {
Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
if (viewMap.containsKey(name)) {
return viewMap.get(name);
} else {
List<Map<String, Object>> activeViewMaps = (List<Map<String, Object>>)
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("com.org.jsf.activeViewMaps");
if (activeViewMaps != null && !activeViewMaps.isEmpty()
&& activeViewMaps.size() > 1) {
Iterator iterator = activeViewMaps.iterator();
if (iterator.hasNext()) {
Map<String, Object> oldViewMap = (Map<String, Object>)
iterator.next();
oldViewMap.clear();
iterator.remove();
}
}
Object object = objectFactory.getObject();
viewMap.put(name, object);
return object;
}
}
Note : Other overridden methods can be empty.
For JSF 2.2:
JSF 2.2 saves the navigated view maps in http session in 'com.Sun.faces.application.view.activeViewMaps' as key. So add the below code in Spring Custom View Scope. No need of listeners as in JSF 2.1
public class ViewScope implements Scope {
public Object get(String name, ObjectFactory objectFactory) {
Map<String, Object> viewMap =
FacesContext.getCurrentInstance().getViewRoot().getViewMap();
if (viewMap.containsKey(name)) {
return viewMap.get(name);
} else {
LRUMap lruMap = (LRUMap) FacesContext.getCurrentInstance().
getExternalContext().getSessionMap().get("com.sun.faces.application.view.activeViewMaps");
if (lruMap != null && !lruMap.isEmpty() && lruMap.size() > 1) {
Iterator itr = lruMap.entrySet().iterator();
while (itr.hasNext()) {//Not req
Entry entry = (Entry) itr.next();
Map<String, Object> map = (Map<String, Object>) entry.getValue();
map.clear();
itr.remove();
break;
}
}
Object object = objectFactory.getObject();
viewMap.put(name, object);
return object;
}
}
Chances are this is a bug. Honestly the Seam 3 implementation wasn't all that great and the CODI one (and also what will be in DeltaSpike) is much better.
I'm starting my first steps in JSF.
I've already read this link
http://docs.oracle.com/javaee/6/tutorial/doc/bnawq.html#bnaww
in regards to map initialization.
The problem is, I want to populate my map with values residing in a file.
How can I do that?
I've tried not using faces-config.xml and calling a support method in the bean's constructor, but my select list box isn't populated.
My bean class:
#ManagedBean
public class ADGroupListBean {
private static final String WITH_ACCESS = "D:\\workspace\\AccessControl\\permissions.txt";
private static final String WITHOUT_ACCESS = "D:\\workspace\\AccessControl\\noPermissions.txt";
private Map<String,String> withAccess, withoutAccess;
private LDAPQueries queries;
public ADGroupListBean(){
withAccess = new LinkedHashMap<String, String>();
withoutAccess = new LinkedHashMap<String, String>();
queries = new LDAPQueries();
initList(WITH_ACCESS, withAccess);
initList(WITHOUT_ACCESS, withoutAccess);
}
private void initList(String filename, Map<String,String> list) {
File f = new File(filename);
if ( !f.exists() && f.getAbsolutePath().equals(WITHOUT_ACCESS) )
{
queries.queryAllGroups(WITHOUT_ACCESS);
}
try
{
Scanner sc = new Scanner(f);
while (sc.hasNext())
{
String group = sc.nextLine();
list.put(group, group);
}
}catch (IOException e) {
e.printStackTrace();
}
}
// public void populateList() {
//
//
// }
public Map<String,String> getWithAccess() {
return withAccess;
}
public Map<String,String> getWithoutAccess() {
return withoutAccess;
}
public void setWithoutAccess(Map<String,String> withoutAccess) {
this.withoutAccess = withoutAccess;
}
public void setwithAccess(Map<String,String> withAccess) {
this.withAccess = withAccess;
}
public void test() {
System.out.println("workssssssssssssssssss");
}
}
As for my JSF file, it is like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head><title>Your Title Here</title>
</h:head>
<h:body>
<h1>Your Heading Here</h1>
<h:form>
<h:selectOneMenu value="teste">
<f:selectItem itemLabel="" itemValue="" />
<f:selectItems value="#{ADGroupListBean.withoutAccess}" />
</h:selectOneMenu>
</h:form>
</h:body>
</html>
I've tested the bean's functions in a test application, and everything works fine.
So my guess is the bean isn't instantiated?
Regards,
Nuno.