I am migrating an old application from Icefaces 1.8 to Icefaces 4.2. I am getting numerous compilation issues as following component classes are no longer available:
HtmlCommandLink (com.icesoft.faces.component.ext.HtmlCommandLink)
HtmlGraphicImage (com.icesoft.faces.component.ext.HtmlGraphicImage)
HtmlOutputLabel (com.icesoft.faces.component.ext.HtmlOutputLabel)
HtmlOutputLink (com.icesoft.faces.component.ext.HtmlOutputLink)
HtmlOutputText(com.icesoft.faces.component.ext.HtmlOutputText)
HtmlPanelGrid (com.icesoft.faces.component.ext.HtmlPanelGrid)
HtmlPanelGroup (com.icesoft.faces.component.ext.HtmlPanelGroup)
MenuBar (com.icesoft.faces.component.menubar.MenuBar)
com.icesoft.faces.component.IceExtended
com.icesoft.faces.component.paneltabset.TabChangeEvent
com.icesoft.faces.component.ext.taglib.Util
com.icesoft.faces.context.effects.JavascriptContext (includeLib)
com.icesoft.faces.component.DisplayEvent
com.icesoft.faces.component.ext.RowSelectorEvent
This is just a small list of elements which are no longer available in icefaces 4. I have lot more other elements as well.
So, the question is, where I can get the list of java implementation of the new components in icefaces 4 which will be substitute for the old Icefaces components?
Please note that I am not using html tag directly inside the xhtml page. I am just using the parent tag and pushing all the rest of the components on the page through java.
<f:view 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:ice="http://www.icesoft.com/icefaces/component"
contentType="text/html">
<ice:portlet styleClass="box1">
<ice:panelGroup styleClass="testPanelGroup">
<ice:outputText value="#{test.Load}" visible="false"/>
<ice:panelGroup binding="#{table.view}"/>
</ice:panelGroup>
</ice:portlet>
</f:view>
My sample java file where i am overriding the java implemenetaion of these tags an then using them in my code
public class HtmlGraphicImage extends
com.icesoft.faces.component.ext.HtmlGraphicImage {
#Override
public Object getValue()
{
Object o = super.getValue();
if (o == null || String.valueOf(o).isEmpty())
return "/images/clear.gif";
return o;
}
}
}
I got the list of the updated components but not their Java implementation.
http://www.icesoft.org/wiki/display/ICE/ICE+to+ACE+Component+Migration+Guide
Related
I have a very simple app. One bean annotated with #Named #SessionScoped and 2 web pages. home.xhtml and list.xhtml. When I set searchForm.hostanme on the first page, and access it again on the 2nd page. I can see from sysout statements that hostname is getting set, but there is a space where that value should be on the list.xhtml page. It's disappearing between home and list. Why?
home.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head></h:head>
<h:form>
<h:outputText value="Hi Mama" />
<h:inputText value="#{searchForm.hostname}" />
<h:commandButton action="list?faces-redirect=true" value="Devices" />
<h:commandButton action="#{searchForm.reset}" value="Reset" immediate="true" type="reset" />
</h:form>
</html>
list.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:outputText value="Device is #{searchForm.hostname}" />
</html>
SearchForm.java
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
#Named
#RequestScoped
public class SearchForm {
String hostname;
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
System.out.println("hostname is "+ hostname);
this.hostname = hostname;
}
public String reset(){
System.out.println("RESETTING");
System.out.println("hostname is "+ hostname);
return "/index.xhtml";
}
}
I'm thinking it might be a scoping issue, but I've tried several scopes and still searchForm.hostname is not avaible by the time I navigate to the list.xhtml page.
I've been reading and reading and reading up on JSF2, but I still can't resolve I hope is a simple problem.
I have a beans.xml file is in WEB-INF.
I come from a seam 2 background so decided I was comfortable with ConversationScoped in this context. It worked like a charm.
Some more thoughts that might help a confused person like me.
As I commented above, I grappled with a similar issue before in this question. As the comments above suggest, this is a scope issue. I realized that it is not only a scoping issue, it is an issue of confusion between CDI and JSF2 managed beans.
Both have a unique set of scopes, but there is some overlap, and in order to not be scratching your head over what should really not be a difficult problem, it is important to
Decide whether to use CDI beans or JSF2 managed beans
Thoroughly learn the scopes assocated with either type of bean
Know which one you are selecting when eclipse offers you 2 choices!
That last one has messed me up more times than I should admit.
Whether to use CDI or JSF2 just google "cdi vs. jsf2". I chose CDI since most things I read said to use CDI. I'm not sure it really makes a difference for my simple app.
Learn your scopes!! There are many articles about scopes, unfortunately I don't understand them as well as I should.
This is a classic for JSF2 users: Communication in JSF2 and I found this helpful as well. (notice same author - BalusC is a good resource for anything JSF2)
As for CDI just stick with the tutorial on Oracle's website.
And as for which library to import -- both JSF and CDI have a SessionScoped, and I think also RequestScoped:
CDI scopes are in javax.enterprise.context.SessionScoped
JSF scopes are in javax.faces.bean.SessionScoped
I consistently just take the first thing eclipse offers me. It can really screw you up so pay attention!
I want to invoke one method through a link from Facelets:
My Facelets code is like:
<h:commandButton value="A" actionListener="#{customerData.searchedCustomerListA}" />
<h:commandLink value="A" actionListener="#{customerData.searchedCustomerListA}"/>
Backing bean code is like:
public void searchedCustomerListA(ActionEvent ae){
customerName = "A";
leftCustomerListAvailable.clear();
if(customerDataBean.getSearchedCustomerList(customerName)!= null)
leftCustomerListAvailable =customerDataBean.getSearchedCustomerList("A");
}
The same code is working for <h:commandButton> but not working for <h:commandLink>. How is this caused and how can I solve it?
The technical difference between <h:commandLink> and <h:commandButton> is that the link uses JavaScript to submit the parent form. So if it doesn't work while a syntactically equivalent button works fine, then that can only mean that either JavaScript is disabled in browser, or that the jsf.js file containing the mandatory helper functions isn't included in the page (which you should easily have noticed by seeing JS errors in the JS console of browser's builtin developer toolset).
So, to fix this problem, you need to verify if JS is enabled in browser and that you've a <h:head> component instead of plain HTML <head> in the template, so that JSF will be able to auto-include the jsf.js file.
Or, if your application's business requirements requires that the application functions as designed with JS disabled, then you should stick to <h:commandButton> and throw in some CSS to make it to look like a link (e.g. remove background, padding, border, inset, etc).
Try this, This sould work.
<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:form>
<h:commandLink type="button" action="#{testBean.tsetLink}">
<h:outputText value="A" />
</h:commandLink>
</h:form>
</html>
ManagedBean
#ManagedBean
#RequestScoped
public class TestBean {
public void tsetLink(){
System.out.println("Link clicked!!!!!!!!!!!!");
}
}
I my case the cause of this issue was a poorly configured url rewriting filter. One of the filters patterns unintentionally matched http://localhost:8080/mysite/javax.faces.resource/jsf.js.xhtml?ln=javax.faces which prevented jsf.js from being loaded. Check this answer: Clicking h:commandLink causes Uncaught ReferenceError: mojarra is not defined.
I use JSF 2.0 (Apache myFaces) on WebSphere Application Server 8.
I have a bean which contains a list of charts (data for jquery HighCharts).
For each chart I need some JSF components + one Highchart Wrapper written as CompositeCompoent (look here)
So I use the ui:repeat function of jsf 2 like this:
<?xml version="1.0" encoding="UTF-8" ?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:hc="http://java.sun.com/jsf/composite/chartComponents"
template="/template/mytemplate.xhtml">
<ui:define name="content">
<ui:repeat value="#{chartCtrl.charts }" var="chart" id="chartrepeat" varStatus="chartStatus">
#{chartStatus.index }
<h:form id="chartform_#{chartStatus.index }">
<!-- some jsf select stuff-->
</h:form>
#{chartStatus.index }
<hc:Chart title="Statistics" id="hcchart_#{chartStatus.index }"
<!-- here's the problem-->
<ui:repeat value="#{chart.series }" var="serie">
<hc:ChartSeries series="#{serie.data }" />
</ui:repeat>
</hc:Chart>
#{chartStatus.index }
</p:panel>
</ui:repeat>
<h:outputScript library="js" name="highcharts.js" />
<h:outputScript library="js/modules" name="exporting.js" />
<h:outputScript library="js" name="jquery-1.9.1.min.js" target="head" />
</ui:define>
</ui:composition>
The #{chartStatus.index } works every where but not in hc:Chart id="".
The generated js and div by this CC contains the id 'hcchart_chartdiv'. The index of the current repeat left.
How can I pass the correct number to the id attribute?
EDIT: Composite Component
Here is a part of the hc:Chart where the ID should be used
<cc:implementation>
<div id="#{cc.id}_chartDiv" />
<!-- Highcharts -_>
<script type="text/javascript">
$(function() {
// Data must be defined WITHIN the function. This prevents
// different charts using the same data variables.
var options = {
credits : {
enabled : false
},
chart : {
renderTo : '#{cc.id}_chartDiv',
....
</script>
When I leave the attribute id in hc:Chart empty, then the generated ID is something like "j_id568185923_1_5f9521d0_chartDiv". But still without :row:.
EDIT 2: IndexOf Approach
I tested another approach to set the ID of my chart.
id="hc_#{chartCtrl.charts.indexOf(chart) }"
I tried to use the IndexOf method of my ArrayList. I implemented HashCode und Equals method in all Classes. When I test it, it works fine.
But when I use it with EL I get -1 returned.
Solution
Just as BalusC said I cant use the ID tag for EL. So I simple created a new attribute in my CC. That works fine (just so easy).
Thanks BalusC.
Does someone has another idea?
The id attribute is evaluated during view build time. The <ui:repeat varStatus> is set during view render time which is after view build time. Essentially, you've the same problem as explained in detail here: JSTL in JSF2 Facelets... makes sense?
Any EL expression in the id attribute must be available during view build time. If you replace <ui:repeat> by <c:forEach> which runs during view build time, then the id must be properly set. An alternative is to just get rid of EL in those id attributes based on <ui:repeat varStatus>. JSF will already automatically suffix the IDs of <ui:repeat> child components with the row index.
Note that the <c:forEach> may have unforeseen side effects when used in combination with view scoped beans and partial state saving enabled. See the aforelinked answer for details.
Is there anyway to use bootstrap related tags in JSF2 components? For example I'm interested in using the bootstrap typeahead feature which requires something like
<h:inputText id="typeahead" type="text" data-provide="typeahead"></h:inputText>
but since data-provide doesn't exist for h:inputText it gets stripped out and so the typeahead feature would obviously not work.
Depends on JSF version you're using.
In JSF 2.0/2.1, it's not possible to specify additional attributes. The JSF HTML renderers will only render predefined attributes. You'd need to create a custom renderer to achieve the desired job. To minimize boilerplate code, you're forced to extend the implementation-specific renderer. It's unclear which one you're using, so here's just a Mojarra targeted example:
import com.sun.faces.renderkit.html_basic.TextRenderer;
public class MyTextRenderer extends TextRenderer {
#Override
protected void getEndTextToRender(FacesContext context, UIComponent component, String currentValue) throws IOException {
Object dataProvide = component.getAttributes().get("data-provide");
if (dataProvide != null) {
context.getResponseWriter().writeAttribute("data-provide", dataProvide, null);
}
super.getEndTextToRender(context, component, currentValue);
}
}
Register it as follows in faces-config.xml to get it to run:
<render-kit>
<renderer>
<component-family>javax.faces.Input</component-family>
<renderer-type>javax.faces.Text</renderer-type>
<renderer-class>com.example.MyTextRenderer</renderer-class>
</renderer>
</render-kit>
In JSF 2.2, it's possible by the new passthrough namespace or the <f:passThroughAttribute> tag. See also What's new in JSF 2.2? - HTML5 Pass-through attributes.
Thus, so:
<html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
...
<h:inputText id="typeahead" a:data-provide="typeahead" />
(note that the type attribute defaults to text already)
Or:
<h:inputText id="typeahead">
<f:passThroughAttribute name="data-provide" value="typeahead" />
</h:inputText>
See also:
Custom HTML tag attributes are not rendered by JSF
I have a base page that uses a ui:include to include another page. The ui:include uses a ui:param to pass a parameter to the included page. The param is read in the PostConstruct method of the included page's controller.
This design works fine until I add a composite component to the base page; once added, the included page controller reports that the ui:param's value is null. Once I remove the composite component from the page, the ui:param is able to be read (i.e. is not null) by the included page's controller. Please help!
Files to reproduce the problem:
myPage.xhtml
<html xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:mycomponents="http://java.sun.com/jsf/composite/mycomponents">
<ui:include src="includePage.xhtml">
<ui:param name="myParam" value="myValue"/>
</ui:include>
<p/>
<mycomponents:myComponent/>
</html>
myIncludedPage.xhtml
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets">
The value of the param is: #{includedPageController.myParam}
</ui:composition>
myComponent.xhtml (placed in "resources/mycomponents")
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface/>
<composite:implementation>
I am the composite component
</composite:implementation>
</html>
IncludedPageController.java
#ManagedBean
public class IncludePageController
{
String myParam;
#PostConstruct
private void init()
{
FaceletContext faceletContext = (FaceletContext)FacesContext.getCurrentInstance().
getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
myParam = (String)faceletContext.getAttribute("myParam");
}
public String getMyParam()
{
return myParam;
}
public void setMyParam(String myParam)
{
this.myParam = myParam;
}
}
See: How do I set Managed Bean field to the value of a ui:param?. There is no standard for doing this sort of thing in the JSF API. A composite or custom component should be used rather than an include/param tag combination.