ManagedBean method is changing dataTable object - primefaces

I have a <p:dataTable /> that lists "System Parameters" of a web page I'm working. One of that parameters is a mail server password, and it is encoded in Base64 in the DB. In the last column of the datatable, I have a button to edit that parameters, and when I click on it, a bootstrap modal is showed with the fields "name" and "value".
I have a ManagedBean with #ViewScoped scope, and a function that also recognizes if the parameter to edit is the mail server password, to have the value decoded. The method gets the object as an argument the datatable iteration object. My problem is that the first time I open the modal, the value of the object is correct, but in second time the object value changes and it generates an exception because the value is already decoded, and the value has a dot inside and it generates the error.
I don't understand why the datatable object value is changed when I never change it literally.
I'm using PrimeFaces, BootsFaces, JSF 2.2. This is my <p:dataTable />:
<p:dataTable value="#{parameterBean.listParameter}" var="p"
paginator="true" rows="10"
reflow="true" id="tblParameter"
emptyMessage="No data available.">
<!-- Some columns -->
<p:column headerText="Options">
<b:commandButton value="Edit" icon="edit" look="info"
ajax="true" update="parametroForm"
onclick="ajax:parameterBean.editParameter(p)"
oncomplete="$('#parameterModal').modal('show');" />
</p:dataTable>
And this is my bean method:
public void editParameter(TblParameter p) {
System.out.println("ENCODE: " + p.getVlrParameter());
this.param = new TblParameter(); //- This is an object in the bean to access it from modal form.
try {
setParam(p);
if (getParam().getIdParameter().equals(new Long(4))) {//- Validate if is the server mail password.
byte[] clv64 = Base64.getDecoder().decode(p.getVlrParameter().getBytes());
getParam().setVlrParameter(new String(clv64));
}
} catch(Exception e) {
System.out.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
Finally, as I said when I open for first time the modal, the output printed is this:
ENCODE: MTIzLjQ1Ng==
But in second time, it shows:
ENCODE: 123.456
java.lang.IllegalArgumentException: Illegal base64 character 2e
at java.util.Base64$Decoder.decode0(Base64.java:714)
at java.util.Base64$Decoder.decode(Base64.java:526)
at com.abcpagos.otis.beans.admin.ParametroBean.editarParametro(ParametroBean.java:146)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)...
If someone could please give me an explanation of this behavior, I would appreciate it very much.

Actually, you do change the parameter accidentially. Have a look at these lines:
byte[] clv64 = Base64.getDecoder().decode(p.getVlrParameter().getBytes());
// ^^^^^^^^^^^^^^^
getParam().setVlrParameter(new String(clv64));
// ^^^^^^^^^^^^^^^
So the second time you try to decode the parameter that's already stored in plain text.

Related

Primefaces datatable filtered rows become blank after sort

My Primefaces table is non-lazy loaded, displays POJOs and support default filtering and sorting.
Filtering works fine alone, sorting works fine alone. But when I type something in any column's filter, and then click a sort key (on any column), all the filtered objects become blank (the number of rows is the correct filtered rows). If I erase the last character in the filter (thus triggering filter), all the filtered rows re-appear OK and the sort order is honored. Here is my datatable:
<p:dataTable id="assets" rows="10" paginator="true" filteredValue="#{assetBean.filteredAssets}"
value="#{assetBean.assetGroups}" var="asset">
<p:column headerText="Location" filterBy="#{asset.installation}" field="installation">
</p:column>
<p:column headerText="Name" filterBy="#{asset.name}" field="name">
</p:column>
<p:column headerText="Type" filterBy="#{asset.udt_id}" field="udt_id">
</p:column>
</p:dataTable>
I tried debugging with logging in the setter and getter of filterValue like this in AssetBean.java:
#javax.inject.Named
#javax.faces.view.ViewScoped
public class AssetBean implements java.io.Serializable {
private List<Asset> filteredAssets;
public List<Asset> getFilteredAssets() {
Logger.getLogger(AssetBean.class.getName()).log(Level.INFO, "getFilteredAssets {0}", filteredAssets.size());
return filteredAssets;
}
public void setFilteredAssets(List<Asset> filteredAssets) {
this.filteredAssets = filteredAssets;
Logger.getLogger(AssetBean.class.getName()).log(Level.INFO, "setFilteredAssets {0}", this.filteredAssets.size());
if (filteredAssets.size()>0) {
Asset a = this.filteredAssets.get(0);
Logger.getLogger(AssetBean.class.getName()).log(Level.INFO, "first name {0}", a.getName());
}
}
....
These are interesting things noted:
getFilteredAssets is never called
setFilteredAssets is first called as expected. When a sortKey is pressed, setFilteredAssets is found to be passed a List of the correct size, but the Asset.name is null. When the filter is changed, setFilteredAssets is found to be passed a List of the correct size, and correct contents so the datatable shows correct data again.
Debugging in the browser shows that the ajax response indeed contains empty rows. For the problematic sort, the POST body of the ajax request contains:
{javax.faces.partial.ajax: "true", ...
main-form:assets_sorting: "true", main-form:assets_skipChildren: "true",
main-form:assets_sortKey: "main-form:assets:j_idt16",
main-form:assets_sortDir: "-1",
main-form:assets:j_idt14filter: "",
main-form:assets:j_idt15filter: "Pla",
main-form:assets:j_idt16filter: "",
}
When I changed the filter, the POST body of the ajax request is the same as above, except main-form:assets:j_idt15filter contains the new value and main-form:assets_sorting, sortKey, sortDir are missing.
My environment TomEE (javaee-web-api 7.0), Primefaces 10.0.0, Omnifaces 3.13, OpenJDK 11.
I solved by a workaround by wrapping a placeholder ajax listener for the sort event to trigger a filter request:
<p:ajax event="sort" listener="#{assetBean.sortPlaceholder}" oncomplete="PF('data-table1').filter()"/>
This seems to be a bug in Primefaces.

How to show a dynamic image in PrimeFaces 6.1 [duplicate]

I am using PrimeFaces 5.3 <p:fileUpload> to upload a PNG image and I would like to show a preview of it in <p:graphicImage> before saving in database.
Here's a MCVE:
<h:form enctype="multipart/form-data">
<p:fileUpload value="#{bean.uploadedFile}" mode="simple" />
<p:graphicImage value="#{bean.image}" />
<p:commandButton action="#{bean.preview}" ajax="false" value="Preview" />
</h:form>
private UploadedFile uploadedFile;
public UploadedFile getUploadedFile() {
return uploadedFile;
}
public void setUploadedFile(UploadedFile uploadedFile) {
this.uploadedFile = uploadedFile;
}
public void preview() {
// NOOP for now.
}
public StreamedContent getImage() {
if (uploadedFile == null) {
return new DefaultStreamedContent();
} else {
return new DefaultStreamedContent(new ByteArrayInputStream(uploadedFile.getContents()), "image/png");
}
}
No error occurring on the backing bean, and the image won't be load and display at front-end. The client mentions that the image returned a 404 not found error.
Your problem is two-fold. It failed because the uploaded file contents is request scoped and because the image is requested in a different HTTP request. To better understand the inner working, carefully read the answers on following closely related Q&A:
Display dynamic image from database with p:graphicImage and StreamedContent
How to choose the right bean scope?
To solve the first problem, you need to read the uploaded file contents immediately in the action method associated with the form submit. In your specific case, that would look like:
private UploadedFile uploadedFile;
private byte[] fileContents;
public void preview() {
fileContents = uploadedFile.getContents();
}
// ...
To solve the second problem, your best bet is to use the data URI scheme. This makes it possible to render the image directly in the very same response and therefore you can safely use a #ViewScoped bean without facing "context not active" issues or saving the byte[] in session or disk in order to enable serving the image in a different request. Browser support on data URI scheme is currently pretty good. Replace the entire <p:graphicImage> with below:
<ui:fragment rendered="#{not empty bean.uploadedFile}">
<img src="data:image/png;base64,#{bean.imageContentsAsBase64}" />
</ui:fragment>
public String getImageContentsAsBase64() {
return Base64.getEncoder().encodeToString(imageContents);
}
Note: I assume that Java 8 is available to you as java.util.Base64 was only introduced in that version. In case you're using an older Java version, use DatatypeConverter.printBase64Binary(imageContents) instead.
In case you happen to use JSF utility library OmniFaces, you can also just use its <o:graphicImage> component instead which is on contrary to <p:graphicImage> capable of directly referencing a byte[] and InputStream bean property and rendering a data URI.
<o:graphicImage value="#{bean.imageContents}" dataURI="true" rendered="#{not empty bean.imageContents}">

sending parameters to javascript function

I have a button which looks like
<p:commandButton id="link" value="E-payment" action="#{controller.ePaymentMethod}"
process="#this" update="#form"
oncomplete="proceedToPayment('{epaymentVo.epaymentEboCode}','{epaymentVo.token}')">
</p:commandButton>
i expect ePaymentMethod to be executed first and on completion of it i am calling another javascript function which is proceedToPayment.
the execution order works as expected.
My epaymentMethod generates token and EpaymentEboCode and sets them on epaymentVo via setters.
My Bean class
class Controller
{
EpaymemtVo epaymentVo;
public void ePaymentMethod()
{
epaymentVo.setEpaymentEboCode(ebpCode);
epaymentVo.setToken(tokenForPayment);
}
}
EpaymentVo is defined as session bean
<managed-bean>
<managed-bean-name>epaymentVo</managed-bean-name>
<managed-bean-class>com.infinite.npsc.Vos.EpaymentVo</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
now my main question is after i set token and EpaymentEboCode on my epaymentVo i expect these values to be sent as parameter to my javascript function.
so whenever i click the E-payment button for the first time null values are passed as parameter. but when i click again the the previously generated token and EpaymentEboCode are sent as paramters.
i want to send currently generated values to be sent as parameters.

How to pass Arrays from backing bean to JavaScript to draw a chart using Chart.js in an Ajax call

I am using prime faces backing bean and Chart.js to draw a chart
I am selecting a row in the data table . On selection of row updating the Canvas which has the Chart in it. I am getting the values on Selection method and building two arrays one for X axis and another for y-axis. How can i pass these arrays to JavaScript to render the chart . I tried Prime faces JSON array to pass to JavaScript. I could not get the values in JavaScrip.
Here is my sample code .xhtml code
<p:dataTable id="myTbl" var="cars" value="#{bean.value}" rowKey="#{bean.carId}" selection="#{bean.selectedCar}" selectionMode="single" reflow="true" >
<p:ajax event="rowSelect" listener="#{bean.onRowSelect}" update=":chartForm" oncomplete="drawChart();" />
</p:dataTable>
<div class= "chart-container" >
<h:outputText id="outputid" value="#{bean.carId}" />
<canvas id="myChart" ></canvas>
</div>
function drawChart(){
var carId = '#{bean.carId}';
alert (carId)
I am selecting a row from the above table. On selection I want to capture the id of the line , get data and display the chart.js chart on same page
here is my bean class
In Bean Class
private String carId;
setter and getter methods
public void onRowSelect(SelectEvent event) {
Cars car= (Cars) event.getObject();
this.carId = car.Id ;
}
I got values into Primefaces JSON Array and passing into JavaScript .In JavaScript I am doing JSON.parse . Initially I got serialization error , so changed the bean to request scoped
The problem is I am not getting any values into JavaScript
I removed JSON Array and and just passing a String
I can get the bean.property on xhtml page as mentioned in my code but not able to get into JavaScript
Am i missing something
you can try to use jsf expression language in javascript code
For example:
//<![CDATA[
var jsVar = #{managedBean.property}
//]]>
Well, if you are concerned with the calling (and passing values) of JS function from bean, then you can call execute of RequestContext.getCurrentInstance() to directly invoke your scripting method from the bean, as following:
RequestContext.getCurrentInstance().execute("yourJSFunction('" + param1 + "');");
However, I think you will still be missing a trick of converting your JSONArray back to JSON object in JS, which you can do as following:
When passed from bean:
function yourJSFunction(coordinatesArray) {
coordinatesArray = JSON.parse(coordinatesArray);
}
Or when using as a bean property:
var coordinatesArr = JSON.parse('#{yourBean.strProperty}');

PropertyNotFoundException for p:column filterValue attribute

we are trying to migrate our application from tomcat/websphere to was liberty profile.
Additionally we are upgrading the myfaces-version, we are using 2.1, to myfaces-2.2.
To save the current state of a table (filtering) we store the filtered value in a map and read it when loading the table (filterValue attribute of p:column).
When initially loading the table the correct method will be used (in our case its getFilterValue in the DataModel). But if we start filtering a column, the method wont be found anymore and the following exception occurs:
javax.el.PropertyNotFoundException: Die Eigenschaft 'getFilterValue' wurde nicht im Typ package.LazyModel gefunden.
javax.el.BeanELResolver$BeanProperties.get(BeanELResolver.java:245)
javax.el.BeanELResolver$BeanProperties.access$300(BeanELResolver.java:222)
javax.el.BeanELResolver.property(BeanELResolver.java:332)
javax.el.BeanELResolver.getType(BeanELResolver.java:83)
javax.el.CompositeELResolver.getType(CompositeELResolver.java:99)
org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver.getType(FacesCompositeELResolver.java:150)
org.apache.el.parser.AstValue.setValue(AstValue.java:199)
org.apache.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:257)
org.jboss.weld.el.WeldValueExpression.setValue(WeldValueExpression.java:64)
org.apache.myfaces.view.facelets.el.ContextAwareTagValueExpression.setValue(ContextAwareTagValueExpression.java:153)
org.primefaces.component.datatable.DataTable.processUpdates(DataTable.java:746)
org.apache.myfaces.context.servlet.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:787)
org.apache.myfaces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:213)
org.primefaces.component.api.UIData.visitTree(UIData.java:822)
The table:
<p:dataTable id="table" var="group"
value="#{bean.lazyModel}"
selection="#{bean.selectedMulti}"
rows="#{bean.lazyModel.rows}" paginator="true"
currentPageReportTemplate="#{msg['data.table.pagereport']}"
paginatorTemplate="#{msg['data.table.paginator']}"
rowsPerPageTemplate="#{msg['data.table.rows']}"
resizableColumns="true" rowKey="#{group.pkId}" lazy="true"
filterDelay="1000" emptyMessage="#{msg['data.table.empty']}"
style="font-size: 8pt;"
tableStyle="font-size: 8pt; table-layout:auto;"
first="#{bean.lazyModel.first_m}"> >
<p:column headerText="Name"
sortBy="#{group.name}" filterBy="#{group.name}"
filterValue="#{bean.lazyModel.getFilterValue('name')}"
filterStyleClass="column_filter" styleClass="wrap">
<h:outputText value="#{group.name}" />
</p:column>
...
The lazymodel:
#Named
#Scope(value = "prototype")
public class LazyModel extends AbstractLazyModel<Brand> {
private static final long serialVersionUID = 2247660292777600670L;
/**
* Konstruktor
*/
public LazyModel() {
super();
}
public Object getFilterValue(final String keyForColumn) {
return this.filterManager.getFilterField(this.getKeyForPage(), keyForColumn);
}
I think this should be the most important things to know.
So, i dont understand what changed between these versions that trigger the exception.
Every help would be great. TIA!
I don't know why this has worked before (it should not have (properly)), but the error you are currently getting is sort of expected. The filterValue attribute should be bound to a property with read and write access. You could bind each column filter value to an individual property, but it is more convenient to use a Map<String,Object> for your filter values.
Bean (lazy model in your case):
private Map<String,Object> filterValues = new HashMap<>();
// ... add getter and setter for filterValues
XHTML:
filterValue="#{bean.lazyModel.filterValues['name']}"