I am able to export 68000 records. When I try to export records more than 80000+ records, it takes more than 2 mins and I will get server timed out error.
<h:commandLink id="excelLinkId">
<p:dataExporter type="xlsx" target="dataTableId" fileName="file"/>
</h:commandLink>
I'm using PrimeFaces 8.0.
Don't use type="xlsx" that stores it all in memory! Use type="xlsxstream" which writes one row at a time and then garbage collects it. I have written out 8000 line PrimeFaces Datatable's no problem with xlsxstream.
To improve performance when exporting to Excel, you should use the following JSF code:
<p:dataExporter type="xlsx" target="myDataTable" options="#{mybBean.excelOpt}" fileName="fichero.xslx" />
In the Java class representing the bean, you should include the following code, where it is indicated not to calculate the width of the columns. Bean code
public ExcelOptions getExcelOpt() {
var excelOpt = new ExcelOptions();
excelOpt.setAutoSizeColumn(false);
return excelOpt;
}
The reason why the export fails or takes long is because the exporter analyzes all the rows of each column and calculates the maximum width that will be applied to that column. This process is not optimal in the POI library of Java.
Related
I'm setting up an input field for currency in my jsf web app and have a backing bean to write the value to. However the converter <f:convertNumber/> doesn't seem to recognize correct input if entered by the user. The initial value can be submitted and numbers can be changed but typing in a value like
1,00 €
won't work. I would like to keep the formatter and also understand how to fix this problem.
I am using JSF 2.3.5-SP2 (Mojarra) with Wildfly 14.0.1 and Java 10.0.1
I narrowed it down to the space between the number and the currency symbol but I don't know how to make <f:convertNumber/> recognize a simple space as a correct input.
After doing a little inspection the original space was identified as a non-breaking space
This is my test code:
test.xhtml
<h:body>
<h:form>
<h:inputText value="#{testModel.number}">
<f:convertNumber type="currency" locale="de_DE" currencyCode="EUR"/>
</h:inputText>
<h:commandButton value="Submit" action="#{testModel.submit}"/>
<h:messages style = "color:red;margin:8px;" />
</h:form>
<h:outputText value="#{testModel.number}"/>
</h:body>
TestModel.java
#Named
#RequestScoped
public class TestModel {
private BigDecimal number;
public String submit(){
return "#";
}
public BigDecimal getNumber() {
if(number==null)number = new BigDecimal("0");
return number;
}
public void setNumber(BigDecimal number) {
this.number = number;
}
}
When changing the number to 1,00 € by only ereasing the 0 of 0,00 € and replacing it with a 1 I get the correct output.
When I replace the (non-breaking) space between the number and the '€' symbol with a simple space the messsage shows the following warning:
j_idt3:j_idt4: '0,00 €' konnte nicht als Währungswert interpretiert werden.
meaning '0,00 €' couldn't be interpreted as a currency value.
I tried to reproduce this using your exact code and was unable to. In fact, any #,## € input seems to be working just fine. Please note that f:convertNumber uses DecimalFormat under the hood - so there might be slight changes not only between JSF versions but potentially also between different versions of Java.
I ran your code with JSF 2.3 and Java 8 and it's parsing the string fine even with a space between the number and the Euro sign. Maybe you are triggering a localization bug that has been fixed in a later version ?
Update
It seems on my specific version of Java (Java 8, 191-b12), JSF implementation (2.3.3.99, Mojarra) and localization rules the behavior is the exact opposite. If I pass a in the inputText the converter will refuse to parse it. Maybe this is indeed a clash between localization rules and the behavior of the component. I had to force this character into the inputText to trigger it though, as the browser will insert simple spaces by default.
Working around the problem
Lucklily after some testing I discovered you can actually work around the problem by supplying a pattern attribute. In your specific case, the solution would be to do something like this,
<f:convertNumber pattern="#,##0.00 ¤" type="currency" locale="de_DE" currencyCode="EUR"/>
This will expect a pattern where the space between the Euro sign and the number is a simple space ( ) character, instead of a which seems to be the default behavior in your environment for some reason.
I have a backend restservice call, returning a value, with which I have to execute a JS function (for simplicity, I took "alert" here, in the frontend. This has to be implemented in JSF, and I'm having a hard time.
And, this is the catch, for performance reasons, I want the backend rest-callto be executed on click.
Here is (amongst many other things), what I have tried:
<p:commandLink action="#{viewingSessionBean.prepareViewingSession(document)}" oncomplete="alert('#{viewingSessionBean.name(document)}')">
<p:graphicImage value="documentViewerPopup.png"/>
</p:commandLink>
Here the bean (shortended to make the point clearer):
#ManagedBean
#ViewScoped
public class ViewingSessionBean implements Serializable {
private String name;
public String prepareViewingSession(Document document) {
name = restClient.call()
hashMap.put(document.getBlobId(), name);
return null; // don't navigate away...
}
public String name(Document document) {
return hashMap.get(document.getBlobId()); // return null if nothing is cached for the document yet there
}
}
I'd like to do something like this (pseudo code... don't have h:commandScript..., too old JSF, no way to upgrade)
<h:commandScript action="alert('#{viewingSessionBean.prepareViewingSession(document)}') />
That's something a bit tricky to accomplish, but stil doable.
One thing you must have in mind first: The JavaScript code you write in a .xhtml is rendered in a 'static' way. But what means 'static'? It means that if you reference a bean variable inside of your JavaScript code, and then update this variable value inside your bean, your printed JavaScript code will not be able to see these changes you just made. In this case you must first update your JavaScript code (using ajax) to get the changes in your variable and only then execute it.
Let's start with your bean:
#ManagedBean
#ViewScoped
public class ViewingSessionBean implements Serializable {
private String variable;
public String getVariable() {
return this.variable;
}
public void updateVariableValue(Document document) {
variable = restClient.call();
}
}
Now, the .xhtml code:
<h:form id="form">
<p:commandLink id="firstLink"
actionListener="#{viewSessionBean.updateVariableValue(document)}"
update=":form:secondLink"
oncomplete="$('#form\\:secondLink').click()"/>
<p:commandLink id="secondLink" onclick="alert('#{viewSessionBean.variable}')" style="display: none;"/>
</h:form>
Note a few things:
First: It was used two commandLinks, and not only one, why? Because at the time of the oncomplete call of the first Link the bean variable is already up-to-date, but your html code is not. So in order to have the updated value of the bean variable we do the following things:
Call the actionListener to update the variable value on the bean;
Make an ajax update on the second Link to get the updated value from the bean;
Call the oncomplete method and call a click to the second Link (now updated with the correct values);
Second: To call the click on the second Link we must escape the two dots on the jQuery call.
Third: The second Link is set with the display: none style to make it invisible in the screen.
Now just some thoughts about it: JSF works pretty well alongside JavaScript, but sometimes we have to make some clumsy tricks like this one to accomplish an "easy" task. I'm not saying that JSF is bad, but I think we could have a more 'out-of-box' approach to these kind of things. Just my opinion though.
I'm trying to establish a bidirectional data binding as follows:
<h:outputText value="#{cc.getAspect('meta').metaInfo.previousValue}" />
But I'm getting the following Exception, only when writing back though (the value is initially displayed just fine upon loading the page):
Caused by: javax.el.PropertyNotFoundException: /resources/meta.xhtml #23,124
value="#{cc.getAspect('meta').metaInfo.previousValue}":
The class 'org.foo.client.jsf.UIComponent' does not have the property 'getAspect'.
Now I'm wondering:
1) The getAspect method is definitely there (double checked, also it works upon read after all). By "property" does JSF denote a "field" and is actually implicitly trying to access setgetAspect or somthing? If so, why?
2) Why would it even try to write, that is to access a setter, on the getAspect in the first place?? The only value that is or should be written is previousValue, just located down the object path cc.getAspect('meta').metaInfo.previousValue which only reads the meta aspect via getAspect.
Any ideas greatly appreciated, thanks
EDIT: Environment: JBoss EAP 6.1.0.GA, JSF Implementation: Mojarra 2.1.19
I use richfaces 3.3.3.Final with Seam and facelet.
I have plugged a profiler on my application and I have a weird behavior.
When I log all exceptions thrown by the application, I have more than 10 000 NoSuchFieldElementException in 10 minutes.
After many search, I found the problem:
When I started an ajax request by a4j:support, the NoSuchFieldElementException is thrown by the AjaxChildrenRenderer in these lines (199-202):
String componentType = (String) component.getClass().getField("COMPONENT_TYPE").get(null);
result = _specialComponentTypes.contains(componentType);
The component variable is a UIInstructions and it has no "COMPONENT_TYPE" field. So, the exception is normal.
This exception is thrown for each html block contained in my page. For example:
<h2>Test</h2>
<span></span>
When I reRender a block with html tag, the exception is thrown.
I have very complex page, so I get many of this exceptions.
How I can do to avoid this exception ? May be a parser option to avoid to go in this class for html block.
Thanks for your help.
As a temporary solution, you could modify the source code to add an instanceof check which should skip that block and then ship the modified source code with your webapp. Ship it either as a single class with identical package/class name in web project itself (javadoc-document it properly), which would always have preference in classloading over the one in the JAR, or as a modified and rebuild JAR file.
if (!(component instanceof UIInstructions)) {
String componentType = (String) component.getClass().getField("COMPONENT_TYPE").get(null);
result = _specialComponentTypes.contains(componentType);
}
As a lasting solution, you should report it as a performance issue to the RichFaces guys so that they get it fixed and release a new update, but I don't think that they will prioritize 3.3.x updates that much. I.e. it might take longer than you'd expect.
I am trying to put versioning around the resources in an application.
If I do like this resources/js/1_0_0/mainscript.js
It does not work. It says RESOURCE_NOT_FOUND
but when I do like this
resources/js/mainscript.js/1_0_0.js
It works. I do not like the way it is organized in the second way. First one looks cool. Any Idea?
I am using Tomcat 7.0, JSF 2.0.9
Update: I was checking primefaces-2-2.1.jar. Since when I checked the page source, I saw this
/javax.faces.resource/jquery/jquery.js.xhtml?ln=primefaces&v=2.2.1">
Then I looked at META-INF/resources/primefaces/jquery/jquery.js
They did not have any versioning in there but how did it append v=2.2.1 in the head
If I do like this resources/js/1_0_0/mainscript.js
It does not work. It says RESOURCE_NOT_FOUND
This will work if you specify js as library name.
<h:outputScript library="js" name="mainscript.js" />
However, this is not the proper usage of a resource library. Rather introduce one.
resources/default/1_0_0/js/mainscript.js
Then you can specify it as follows:
<h:outputScript library="default" name="js/mainscript.js" />
They did not have any versioning in there but how did it append v=2.2.1 in the head
It's done by PrimeResource which kicks in on resource requests with ln=primefaces parameter. Its getRequestPath() has the following implementation:
#Override
public String getRequestPath() {
return super.getRequestPath() + "&v=" + Constants.VERSION;
}
Where Constants is the PrimeFaces specific constants file which is updated with every PF version.