Domain based I18N with JSF2.0 - jsf

I have to implement I18N based on domain using JSF2.
For example if the domain is
www.bookstore.com --> it should go to english site
www.bookstore.com.cn --> it should go to chinese site
www.bookstore.co.jp --> it should go to japanese site
We have all properties files with proper translation.
When i change my browser language/locale, i could able to see the translated content.
But we don't need that behavior actually.
I am setting the locale based on domain in Filter, It seems not working.
Here is my code, What is wrong in this code, Where is the problem ?
AuthenticationFilter.java
public class AuthenticationFilter implements Filter {
private static Log log = LogFactory.getLog(AuthenticationFilter.class);
#Override
public void init(FilterConfig config) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
FacesContext facesContext = FacesUtil.getFacesContext(httpRequest, httpResponse);
facesContext.getExternalContext().setResponseCharacterEncoding("UTF-8");
Locale requestLocale = LocaleUtil.getLocaleFromDomain(httpRequest);
if(requestLocale == null){
requestLocale = LocaleUtil.getDefault();
}
facesContext.getViewRoot().setLocale(requestLocale);
chain.doFilter(httpRequest, httpResponse);
}
#Override
public void destroy() {
}
}
FacesUtil.java
public class FacesUtil {
public static FacesContext getFacesContext(HttpServletRequest request, HttpServletResponse response) {
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext == null) {
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
facesContext = contextFactory.getFacesContext(request.getSession().getServletContext(), request, response, lifecycle);
UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, "");
facesContext.setViewRoot(view);
FacesContextWrapper.setCurrentInstance(facesContext);
}
return facesContext;
}
// Wrap the protected FacesContext.setCurrentInstance() in a inner class.
private static abstract class FacesContextWrapper extends FacesContext {
protected static void setCurrentInstance(FacesContext facesContext) {
FacesContext.setCurrentInstance(facesContext);
}
}
}
LocaleUtil.java
public class LocaleUtil {
public static Locale getLocaleFromDomain(HttpServletRequest request){
Locale locale=Locale.getDefault();
String domain = request.getHeader("HOST");
if(domain.contains(".com.cn"))
{
locale = new Locale(Locale.SIMPLIFIED_CHINESE.getLanguage(), Locale.CHINA.getCountry());
}else if(domain.contains(".co.jp"))
{
locale = new Locale(Locale.JAPANESE.getLanguage(), Locale.JAPAN.getCountry());
}else if(domain.contains(".co.kr"))
{
locale = new Locale(Locale.KOREAN.getLanguage(), Locale.KOREA.getCountry());
}else if(domain.contains(".com.tw"))
{
locale = new Locale(Locale.CHINESE.getLanguage(), Locale.TAIWAN.getCountry());
}
return locale;
}
public static Locale getDefault() {
Locale defaultLocale = new Locale("en", "US");
return defaultLocale;
}
}
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
<application>
<locale-config>
<default-locale>en</default-locale>
<supported-locale>en_US</supported-locale>
<supported-locale>zh</supported-locale>
<supported-locale>zh_CN</supported-locale>
<supported-locale>zh_TW</supported-locale>
<supported-locale>ja</supported-locale>
<supported-locale>ja_JP</supported-locale>
</locale-config>
<resource-bundle>
<base-name>com.bookstore.component.BookStoreTextHandler</base-name>
<var>msg</var>
</resource-bundle>
</application>
</faces-config>
BookStoreTextHandler.java
public class BookStoreTextHandler extends ResourceBundle {
protected static final String BUNDLE_NAME = "/var/app/conf/bookstore";
protected static final String BUNDLE_EXTENSION = "properties";
protected static final Control UTF8_CONTROL = new UTF8Control();
public BookStoreTextHandler() {
Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
setParent(ResourceBundle.getBundle(BUNDLE_NAME, locale, UTF8_CONTROL));
}
#Override
protected Object handleGetObject(String key) {
return parent.getObject(key);
}
#Override
public Enumeration<String> getKeys() {
return parent.getKeys();
}
protected static class UTF8Control extends Control {
#Override
public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
throws IllegalAccessException, InstantiationException, IOException {
String bundleName = toBundleName(baseName, locale);
String resourceName = toResourceName(bundleName, BUNDLE_EXTENSION);
ResourceBundle bundle = null;
InputStreamReader reader = null;
FileInputStream fis = null;
try {
File file = new File(resourceName);
if (file.isFile()) { // Also checks for existance
fis = new FileInputStream(file);
reader = new InputStreamReader(fis, Charset.forName("UTF-8"));
bundle = new PropertyResourceBundle(reader);
}
} finally {
IOUtils.closeQuietly(reader);
IOUtils.closeQuietly(fis);
}
return bundle;
}
}
}
i have bookstore.properties, bookstore_en.properties, bookstore_en_US.properties, bookstore_zh.properties, bookstore_zh_CN.properties, bookstore_zh_TW.properties, bookstore.properties_ja, bookstore_ja_JP.properties, files in /var/app/conf/ location.
introPage.xhtml
<ui:composition lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:ui="http://java.sun.com/jsf/facelets">
<div class="frame">
<h1>#{msg['bookstore.intro.title']}</h1>
</div>
<div>
<p style="line-height: 1.6em; font-family: Verdana, Arial, sans-serif;">
<h:outputText value="#{msg['bookstore.intro.paragraph.1']}" escape="false"/>
</p>
<p style="line-height: 1.6em; font-family: Verdana, Arial, sans-serif;">
<h:outputText value="#{msg['bookstore.intro.paragraph.2']}" escape="false"/>
</p>
<p style="line-height: 1.6em; font-family: Verdana, Arial, sans-serif; font-weight: bold;">
<h:outputText value="#{msg['bookstore.intro.paragraph.3']}" escape="false"/>
</p>
</div>
</ui:composition>
When i am trying from different domains [ i have changed my host file locally ],
when i debug the filter code, it is giving correct Locale based on domain.
But don't know why always getting english content.
But if i change the browser language, i can see the translated content.
What is wrong in this code ?

Related

How to get UISelectMany custom component value in a managed bean

I have a project which consist in a treeview of a folder.
I decided to create a custom component.
The XHTML looks great, I can get the request param of the selected files on the decode method.
The problem is: I can't obtain the value on a managedBean attribute (see submit method)...
here is my code, I don't understand what is wrong or I miss...
Custom Component
#FacesComponent(createTag = true, tagName = "indexComponent", namespace = "http://index.com/tags")
public class IndexComponent extends UISelectMany{
private String pathString = "/home/test/";
private List<Path> filesNames = new ArrayList<>();
private static String NAME_CHKBOX = "checkbox";
IndexComponent instance = this;
public IndexComponent getInstance() {
return instance;
}
public void setInstance(IndexComponent instance) {
this.instance = instance;
}
#Override
public String getFamily() {
return "treeview";
}
#Override
public void encodeBegin(FacesContext context) throws IOException{
ResponseWriter writer = context.getResponseWriter();
writer.startElement("ul", this);
writer.writeAttribute("data-role", "treeview", null);
writer.writeAttribute("id", this.getClientId(context), null);
Files.walkFileTree(Paths.get(pathString), new HashSet<>(),2, new FileVisitor<Path>() {
#Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
filesNames.add(dir);
writer.startElement("li", instance);
writer.writeAttribute("data-caption", dir.getFileName() , null);
writer.writeAttribute("class", "" , null);
writer.startElement("ul", instance);
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
filesNames.add(file);
writer.startElement("li", instance);
writer.startElement("input", instance);
writer.writeAttribute("type", "checkbox" , null);
writer.writeAttribute("name", getHtmlNameCheckBox(context) , null);
writer.writeAttribute("value", file.getFileName() , null);
writer.writeAttribute("data-role", "checkbox" , null);
writer.writeAttribute("data-caption", file.getFileName() , null);
writer.writeAttribute("title", "" , null);
writer.endElement("input");
writer.endElement("li");
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
writer.endElement("li");
writer.endElement("ul");
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
writer.startElement("li", instance);
writer.writeAttribute("data-caption", file.getFileName() , null);
writer.endElement("li");
return FileVisitResult.CONTINUE;
}
});
writer.endElement("ul");
instance.encodeEnd(context);
}
public List<Path> getFilesNames() {
return filesNames;
}
public void setFilesNames(List<Path> filesNames) {
this.filesNames = filesNames;
}
#Override
public void decode(FacesContext context) {
String[] result = context.getExternalContext().getRequestParameterValuesMap().get( getHtmlNameCheckBox(context) );
if(result != null && result.length > 0) {
List<String> liste = Arrays.asList( result );
this.setSubmittedValue(liste);
}
}
private String getHtmlNameCheckBox(FacesContext context){
return String.format("%s:%s", this.getClientId(context), NAME_CHKBOX);
}
}
ManadgeBean
#Named
#ViewScoped
public class IndexBean implements Serializable{
private static final long serialVersionUID = -1L;
private List<String> filesNames;
#PostConstruct
public void init() {
filesNames = new ArrayList<>();
}
public void submit() {
LogUtils.info("submit !!!");
for (String s : filesNames) {
LogUtils.info(s);
}
}
public List<String> getFilesNames() {
return filesNames;
}
public void setFilesNames(List<String> filesNames) {
this.filesNames = filesNames;
}
}
XHTML
<!DOCTYPE html>
<h: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"
xmlns:t="http://index.com/tags"
xmlns:composite="http://java.sun.com/jsf/composite">
<h:head>
<h:outputStylesheet name="metro-all.css" library="css" />
<h:outputScript name="jquery-3.3.1.min.js" library="js" />
<h:outputScript name="metro.js" library="js" />
</h:head>
<h:body>
<h:form>
<t:indexComponent value="#{indexBean.filesNames}" />
<h:commandButton actionListener="#{indexBean.submit()}" type="submit" styleClass="button primary" value="Submit" />
</h:form>
</h:body>
</h:html>
Note : I don't want to use Primefaces or other framework.

How can I add Liferay's CKEditor to my JSF portlet?

I want to add Liferay's CKEditor to my JSF portlet. I tried to find a way to add the CKEditor in JSF, but all the examples/solutions show how to add the CKEditor in a JSP not JSF.
I am using Liferay Portal 6.0 EE.
You can add the CKEditor to a JSF page by including the Liferay Faces Portal jar* in your project, and writing code similar to one of the following examples:
Liferay 6.2+ Example:
<portal:inputRichText value="#{backing.value}" />
Check out the Liferay Faces Showcase for live examples and more details.
Deprecated Liferay 6.2 and 6.1 Example:
<liferay-ui:input-editor editorImpl="editor.wysiwyg.default" value="#{backing.value}">
Deprecated Liferay 6.0 EE Example:
<liferay-ui:input-editor editorImpl="ckeditor" value="#{backing.value}">
*Since you are using Liferay 6.0 EE, you need to use LF Portal version 3.0.5-ga6. Consult the the Liferay Faces Version Scheme for more information on compatible Liferay Faces and Liferay Portal versions.
Use the below code. Reference Liferay Faces Showcase
inputRichText.xhtml
<alloy:outputStylesheet library="css" name="input-rich-text.css" />
<alloy:form id="exampleForm">
<alloy:field id="commentsField" label="#{i18n['comments']}" styleClass="input-rich-text-field">
<alloy:message id="commentsMessage" for="comments" />
</alloy:field>
<!-- Note: In this example, portal:inputRichText is intentionally not a child of alloy:field in order -->
<!-- to prevent it from being unnecessarily reinitialized when the alloy:field is re-rendered via Ajax. -->
<portal:inputRichText id="comments" label="#{i18n['comments']}"
required="#{showcaseModelBean.selectedComponent.required}"
value="#{inputRichTextBacking.applicant.comments}" />
<alloy:commandButton actionListener="#{inputRichTextBacking.submit}"
render=":exampleForm:commentsField :modelValue" value="#{i18n['submit']}" />
</alloy:form>
<alloy:outputText id="modelValue" value="#{inputRichTextBacking.applicant.comments}" />
InputRichTextBacking.java
#ManagedBean
#RequestScoped
public class InputRichTextBacking {
private static final Logger logger = LoggerFactory.getLogger(InputRichTextBacking.class);
private Applicant applicant;
private boolean resizable = true;
#PostConstruct
public void init() {
applicant = new Applicant();
if (ViewParamUtil.getUsage().equals("default-value")) {
applicant.setComments(
"<p>This is some <strong>bold</strong> text\nand this is some <em>italic</em> text.</p>");
}
}
public void submit() {
logger.info("You entered comments: " + applicant.getComments());
}
public void valueChangeListener(ValueChangeEvent valueChangeEvent) {
FacesContext facesContext = FacesContext.getCurrentInstance();
PhaseId phaseId = facesContext.getCurrentPhaseId();
logger.debug("valueChangeListener: phaseId=[{0}]", phaseId.toString());
String phaseName = phaseId.getName();
FacesMessage facesMessage = new FacesMessage("The valueChangeListener method was called during the " +
phaseName + " phase of the JSF lifecycle.");
facesContext.addMessage(null, facesMessage);
}
public Applicant getApplicant() {
return applicant;
}
public boolean isResizable() {
return resizable;
}
public void setResizable(boolean resizable) {
this.resizable = resizable;
}
}
Applicant.java
public class Applicant implements Serializable {
private static final long serialVersionUID = 4661552363081858711L;
private String city;
private String comments;
private Date dateOfBirth;
private String emailAddress;
private String firstName;
private String lastName;
private String phoneNumber;
private String postalCode;
private Long provinceId;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public Long getProvinceId() {
return provinceId;
}
public void setProvinceId(Long provinceId) {
this.provinceId = provinceId;
}
}
input-rich-text.css
/* The Liferay Portal margin-bottom is 30px for div elements with class="control-group" (such as alloy:field). */
/* Set the margin-bottom to zero since the portal:inputRichText is not a child of the alloy:field component tag. */
.aui div.input-rich-text-field.control-group {
margin-bottom: 0px;
}
.aui div.portal-input-rich-text {
margin-bottom: 30px;
}
input-rich-text.properties
#
# The default key used by the editorImpl attribute is found in the Liferay portal.properties file:
#
# editor.wysiwyg.default=ckeditor
#
# For more information, see:
#
# https://github.com/liferay/liferay-portal/blob/6.2.1-ga2/portal-impl/src/portal.properties#L5282
#
# Alternate keys for BBCode and Creole can be specified in a custom portal-ext.properties file.
#
# For example:
#
com.liferay.faces.demos.showcase.ckeditor=ckeditor
com.liferay.faces.demos.showcase.ckeditor_bbcode=ckeditor_bbcode
com.liferay.faces.demos.showcase.ckeditor_creole=ckeditor_creole
You can use:
<aui:fieldset>
<script type="text/javascript">
function <portlet:namespace />initEditor() {
}
</script>
<aui:field-wrapper label="content">
<liferay-ui:input-editor width="100%" />
<aui:input name="content" type="hidden" />
</aui:field-wrapper>
</aui:fieldset>

JSF 2.0 encodeAll() invoked prior to sessionCreated()

I have created a custom component in JSF 2.0. Its purpose is to display a session attribute value in a input text box. I want the session attribute to be created in HttpSessionListener sessionCreated method. The problem is encodeAll method is getting invoked prior to sessionCreated method. What should I do to make sessionCreated invoked prior to encodeAll?
web.xml
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/components.taglib.xml</param-value>
</context-param>
<listener>
<listener-class>mycomp.jsf.listener.MyListener</listener-class>
</listener>
components.taglib.xml
<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
version="2.0">
<namespace>http://mycomp/jsf/components</namespace>
<tag>
<tag-name>mycomp</tag-name>
<component>
<component-type>MyComp</component-type>
</component>
</tag>
</facelet-taglib>
MyListener.java
public class MyListener implements HttpSessionListener {
#Override
public void sessionCreated(HttpSessionEvent event) {
HttpSession session = event.getSession();
session.setAttribute("sessionid", session.getId());
}
#Override
public void sessionDestroyed(HttpSessionEvent se) {
}
}
MyComp.java
#FacesComponent(value = "MyComp")
public class MyComp extends UIComponentBase {
public MyComp() {
setRendererType(null);
}
protected Class getComponentClass() {
return this.getClass();
}
#Override
public void decode(FacesContext context) {
//some logic
}
#Override
public void encodeAll(FacesContext context) throws IOException {
String clientId = getClientId(context) + ":token";
HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
String sessionId = (String) session.getAttribute("sessionid");
if (sessionId == null || "".equals(sessionId)) {
throw new RuntimeException("sessionid is missing!");
}
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", this);
writer.writeAttribute("type", "text", "type");
writer.writeAttribute("name", clientId, "name");
writer.writeAttribute("value", sessionId, "value");
writer.endElement("input");
}
#Override
public String getFamily() {
return null;
}
}
index.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:t="http://mycomp/jsf/components">
<h:head>
</h:head>
<h:body>
<h:form>
<t:mycomp />
</h:form>
</h:body>
</html>
Replace getSession(false) by getSession(true).
HttpSession session = (HttpSession) context.getExternalContext().getSession(true);
The boolean tells whether the session should be created or not when it isn't created yet. With getSession(false) you're thus risking getting a null when it isn't been created at that point yet and hence the NullPointerException whenever you call any methods on it. See also the javadoc.
Unrelated to the concrete problem, cleaner is to use ExternalContext#getSessionMap() instead. Having "raw" javax.servlet imports in your JSF code namely usually indicates smells in the JSF code. I.e. something is been done unnecessarily overcomplicated. You should then look for simpler ways with pure JSF API.
Replace
HttpSession session = (HttpSession) context.getExternalContext().getSession(true);
String sessionId = (String) session.getAttribute("sessionid");
if (sessionId == null || "".equals(sessionId)) {
throw new RuntimeException("sessionid is missing!");
}
by
String sessionId = (String) context.getExternalContext().getSessionMap().get("sessionid");
if (sessionId == null || "".equals(sessionId)) {
throw new RuntimeException("sessionid is missing!");
}

No View in JSP Example

I have a problem with the view in JSP (Java EE)
Only the heading is shown.
My Code:
Entitiy Class (Konto);
#Entity
public class Konto implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable=false)
#NotNull(message="Kontonummer muss angegenben werden")
#Pattern(regexp="[0-9][0-9][0-9][0-9]")
private String kontonummer;
#Column(nullable=false)
#NotNull(message="Kontostand muss angegeben werden")
#DefaultValue(value="0.0")
private Double ktostd;
#Column(nullable=false)
#DecimalMin(value="0", message="Der Zins muss zw. 0 und 10 % liegen")
#DecimalMax(value="0.1", message="Der Zins muss zw. 0 und 10 % liegen")
private Double habenZins;
#ManyToOne
#JoinColumn(nullable=false)
#NotNull(message="Besitzer muss angegeben werden")
private Besitzer besitzer;
public Besitzer getBesitzer() {
return besitzer;
}
public void setBesitzer(Besitzer besitzer) {
this.besitzer = besitzer;
}
public Double getHabenZins() {
return habenZins;
}
public void setHabenZins(Double habenZins) {
this.habenZins = habenZins;
}
public String getKontonummer() {
return kontonummer;
}
public void setKontonummer(String kontonummer) {
this.kontonummer = kontonummer;
}
public Double getKtostd() {
return ktostd;
}
public void setKtostd(Double ktostd) {
this.ktostd = ktostd;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Konto)) {
return false;
}
Konto other = (Konto) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "at.korn.entity.NewEntity[ id=" + id + " ]";
}
}
Kontolist.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h1>Kontoliste</h1>
<h:form>
<h:dataTable value="#{kontolist.kontos}" var="konto">
<h:column>
<f:facet name="header">
<h:outputText value="Kontonummer"></h:outputText>
</f:facet>
<h:outputText value="#{konto.kontonummer}"></h:outputText>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
KontoList Controller:
#ManagedBean
#SessionScoped
public class Kontolist {
#EJB
KontoFacadeLocal kontofacade;
private List<Konto> kontos;
/** Creates a new instance of kontolist */
public Kontolist() {
kontos = kontofacade.findAll();
}
public KontoFacadeLocal getKontofacade() {
return kontofacade;
}
public void setKontofacade(KontoFacadeLocal kontofacade) {
this.kontofacade = kontofacade;
}
public List<Konto> getKontos() {
setKontos(kontofacade.findAll());
return kontos;
}
public void setKontos(List<Konto> kontos) {
this.kontos = kontos;
}
}
Problem:
Only the header is shown. In the source from the browser is the same code without html injection (like value="#{konto.kontonummer}")
First of all, that is not a JSP file. That's a Facelets (XHTML) file. JSP is an ancient view technology. Facelets is the successor of JSP.
So, your concrete problem is that the JSF tags are not been parsed? That can happen when the request URL did not match the URL pattern of the FacesServlet as definied in web.xml. If it is for example *.jsf, then you'd need to change the request URL from
http://localhost:8080/contextname/kontolist.xhtml
to
http://localhost:8080/contextname/kontolist.jsf
However, much better is to just change the URL pattern of the FacesServlet to *.xhtml so that you do not need to fiddle with virtual URLs and introduce security constraints to prevent the enduser from accidently or awaringly viewing the raw *.xhtml pages.
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
See also:
What is the difference between creating JSF pages with .jsp or .xhtml or .jsf extension
Unrelated to the concrete problem, you've by the way a NullPointerException bug in your code. Replace
public Kontolist() {
kontos = kontofacade.findAll();
}
by
#PostConstruct
public void init() {
kontos = kontofacade.findAll();
}
Injected dependencies are namely not available during construction. The getter and setter for the kontofacate are also entirely superfluous, I'd remove them to prevent future confusion and abuse.

Downloading file from IceFaces tree

I'm still on the road of learning JSF. I have an IceFaces tree with an IceFaces commandLink to try to download a file. So far this is my xhtml and my backing bean. When I click the commandLink it just prints the two messages and then it does nothing and it does not show any warning any error at all... How to know what's happening? What am I missing?
Cheers
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"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ice="http://www.icesoft.com/icefaces/component">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<ice:tree id="tree"
value="#{treeBean.model}"
var="item"
hideNavigation="false"
hideRootNode="false"
imageDir="./images/">
<ice:treeNode>
<f:facet name="icon">
<ice:panelGroup style="display: inline">
<h:graphicImage value="#{item.userObject.icon}"/>
</ice:panelGroup>
</f:facet>
<f:facet name="content">
<ice:panelGroup style="display: inline">
<ice:commandLink action="#{treeBean.doDownload(item.userObject.fileAbsolutePath)}">
<ice:outputText value="#{item.userObject.text}"/>
</ice:commandLink>
</ice:panelGroup>
</f:facet>
</ice:treeNode>
</ice:tree>
</h:form>
</h:body>
</html>
BEAN
#ManagedBean
#ViewScoped
public class TreeBean implements Serializable {
private final DefaultTreeModel model;
/** Creates a new instance of TreeBean */
public TreeBean() {
// create root node with its children expanded
DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
IceUserObject rootObject = new IceUserObject(rootTreeNode);
rootObject.setText("Root Node");
rootObject.setExpanded(true);
rootObject.setBranchContractedIcon("./images/tree_folder_close.gif");
rootObject.setBranchExpandedIcon("./images/tree_folder_open.gif");
rootObject.setLeafIcon("./images/tree_document.gif");
rootTreeNode.setUserObject(rootObject);
// model is accessed by by the ice:tree component via a getter method
model = new DefaultTreeModel(rootTreeNode);
// add some child nodes
for (int i = 0; i < 3; i++) {
DefaultMutableTreeNode branchNode = new DefaultMutableTreeNode();
FileSourceUserObject branchObject = new FileSourceUserObject(branchNode);
branchObject.setText("SteveJobs.jpg");
branchObject.setFileAbsolutePath("/Users/BRabbit/Downloads/SteveJobs.jpg");
branchObject.setBranchContractedIcon("./images/tree_folder_close.gif");
branchObject.setBranchExpandedIcon("./images/tree_folder_open.gif");
branchObject.setLeafIcon("./images/tree_document.gif");
branchObject.setLeaf(true);
branchNode.setUserObject(branchObject);
rootTreeNode.add(branchNode);
}
}
public DefaultTreeModel getModel() {
return model;
}
public void doDownload(String fileAbsolutePath) {
System.out.println(fileAbsolutePath);
File file = new File(fileAbsolutePath);
if(file.exists())
System.out.println("Yes"); //It exists !
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
externalContext.setResponseHeader("Content-Type", externalContext.getMimeType(file.getName()));
externalContext.setResponseHeader("Content-Length", String.valueOf(file.length()));
externalContext.setResponseHeader("Content-Disposition", "attachment;filename=\"" + file.getName() + "\"");
InputStream input = null;
OutputStream output = null;
try {
input = new FileInputStream(file);
output = externalContext.getResponseOutputStream();
IOUtils.copy(input, output);
} catch (FileNotFoundException ex) {
Logger.getLogger(TreeBean.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(TreeBean.class.getName()).log(Level.SEVERE, null, ex);
} finally {
IOUtils.closeQuietly(output);
IOUtils.closeQuietly(input);
}
facesContext.responseComplete();
}
}
Bean's object
public class FileSourceUserObject extends IceUserObject{
String fileAbsolutePath;
public FileSourceUserObject(DefaultMutableTreeNode wrapper) {
super(wrapper);
}
public String getFileAbsolutePath(){
return fileAbsolutePath;
}
public void setFileAbsolutePath(String fileAbsolutePath){
this.fileAbsolutePath = fileAbsolutePath;
}
}
Finally I did it!
Here's some code that allows the user to see a tree (of Files) and download them.
XHTML
<ice:tree id="tree"
value="#{treeBean.model}"
var="item"
hideNavigation="false"
hideRootNode="false"
imageDir="./images/">
<ice:treeNode>
<f:facet name="icon">
<ice:panelGroup style="display: inline">
<h:graphicImage value="#{item.userObject.icon}"/>
</ice:panelGroup>
</f:facet>
<f:facet name="content">
<ice:panelGroup style="display: inline-block">
<ice:outputResource resource="#{item.userObject.resource}"
fileName="#{item.userObject.text}"
shared="false"/>
</ice:panelGroup>
</f:facet>
</ice:treeNode>
</ice:tree>
BACKING BEAN
#ManagedBean
#ViewScoped
public class TreeBean implements Serializable {
private final DefaultTreeModel model;
public TreeBean() {
DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
FileSourceUserObject rootObject = new FileSourceUserObject(rootTreeNode);
rootObject.setText("Root Node");
rootObject.setExpanded(true);
rootObject.setBranchContractedIcon("./images/tree_folder_close.gif");
rootObject.setBranchExpandedIcon("./images/tree_folder_open.gif");
rootTreeNode.setUserObject(rootObject);
// model is accessed by by the ice:tree component via a getter method
model = new DefaultTreeModel(rootTreeNode);
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
// add some child nodes
for (int i = 0; i < 3; i++) {
DefaultMutableTreeNode branchNode = new DefaultMutableTreeNode();
FileSourceUserObject branchObject = new FileSourceUserObject(branchNode);
branchObject.setText("Test.jpg");
branchObject.setResource(new SRCResource("/<filePath>/Test.jpg"));
branchObject.setBranchContractedIcon("./images/tree_folder_close.gif");
branchObject.setBranchExpandedIcon("./images/tree_folder_open.gif");
branchObject.setLeafIcon("./images/tree_document.gif");
branchObject.setLeaf(true);
branchNode.setUserObject(branchObject);
rootTreeNode.add(branchNode);
}
}
public DefaultTreeModel getModel() {
return model;
}
}
SRCResource
public class SRCResource implements Resource {
private String fileAbsolutePath;
private final Date lastModified;
public SRCResource(String fileAbsolutePath) {
this.fileAbsolutePath = fileAbsolutePath;
this.lastModified = new Date();
}
#Override
public String calculateDigest() {
return "No lo calcularé jamás !!";
}
#Override
public InputStream open() throws IOException {
return (InputStream)(new FileInputStream(fileAbsolutePath));
}
#Override
public Date lastModified() {
return lastModified;
}
#Override
public void withOptions(Options optns) throws IOException {
}
public String getFileAbsolutePath() {
return fileAbsolutePath;
}
public void setFileAbsolutePath(String fileAbsolutePath) {
this.fileAbsolutePath = fileAbsolutePath;
}
}
Web.xml
Add the following
<servlet>
<servlet-name>Resource Servlet</servlet-name>
<servlet-class>com.icesoft.faces.webapp.CompatResourceServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Resource Servlet</servlet-name>
<url-pattern>/xmlhttp/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/icefaces/*</url-pattern>
</servlet-mapping>
And that's it ! Simply adapt the code to your needs !
Cheers !
More info on http://wiki.icefaces.org/display/ICE/Adding+ICEfaces+to+Your+Application

Resources