Icefaces tree + outputResource - jsf

I implemented a tree with an outputResource as "content" (see Downloading file from IceFaces tree).
However, when I try to download a file (I have only txt or csv files) I get the HTTP 500 Status error.
The tree structure is something like
Root
|-infoFiles
| |-A.csv
| |-B.csv
|-validateFiles
| |-C.txt
| |-D.txt
And the exception once I click on the resource is
java.io.FileNotFoundException: C:\SRC\dataFiles\998\validateFiles (Access denied)
java.io.FileInputStream.open(Native Method)
java.io.FileInputStream.<init>(FileInputStream.java:138)
java.io.FileInputStream.<init>(FileInputStream.java:97)
mx.gob.sagarpa.utilidades.FileResource.open(FileResource.java:39)
com.icesoft.faces.component.outputresource.RegisteredResource.open(OutputResource.java:474)
com.icesoft.faces.context.ResourceRegistryLocator$DynamicResourceDispatcherAdapter$DynamicResourceAdapter.open(ResourceRegistryLocator.java:117)
org.icefaces.impl.push.DynamicResourceDispatcher$ResourceServer.respond(DynamicResourceDispatcher.java:224)
org.icefaces.impl.push.DynamicResourceDispatcher$ResourceServer.handleResourceRequest(DynamicResourceDispatcher.java:201)
org.icefaces.impl.push.DynamicResourceDispatcher$Mapping.handleResourceRequest(DynamicResourceDispatcher.java:370)
org.icefaces.impl.push.DynamicResourceDispatcher.handleResourceRequest(DynamicResourceDispatcher.java:89)
org.icefaces.application.ResourceRegistry.handleResourceRequest(ResourceRegistry.java:75)
org.icefaces.impl.application.WindowScopeManager.handleResourceRequest(WindowScopeManager.java:165)
javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125)
javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:591)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
Sometimes it happens just with csv files and sometimes even with txt
Tree.xhtml
<ice:tree id="tree"
value="#{treeBean.model}"
var="item"
hideRootNode="false"
hideNavigation="false"
>
<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.resource.filename}"
mimeType="#{item.userObject.resource.mimeType}"
/>
</ice:panelGroup>
</f:facet>
</ice:treeNode>
</ice:tree>
TreeBean.java
#ManagedBean
#ViewScoped
public class TreeBean implements Serializable {
private DefaultTreeModel model;
public final String openFolderImg = "./img/tree_folder_open.gif";
public final String closeFolderImg = "./img/tree_folder_close.gif";
public final String fileImg = "./img/tree_document.gif";
#ManagedProperty("#{userBean}")
private UserBean userBean;
#PostConstruct
public void init() {
// create root node with its children expanded
DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
FileResourceUserObject rootObject = new FileResourceUserObject(rootTreeNode);
rootObject.setText("Sistema de Rendición de Cuentas");
rootObject.setExpanded(true);
rootObject.setResource(new FileResource("Sistema de Rendición de Cuentas", null));
rootObject.setBranchContractedIcon(openFolderImg);
rootObject.setBranchExpandedIcon(closeFolderImg);
rootTreeNode.setUserObject(rootObject);
// model is accessed by the ice:tree component
model = new DefaultTreeModel(rootTreeNode);
File f = new File("./998/");
createTree(f, rootTreeNode);
}
public DefaultTreeModel getModel() {
return model;
}
public UserBean getUserBean() {
return userBean;
}
public void setUserBean(UserBean userBean) {
this.userBean = userBean;
}
private void createTree(File fileRoot, DefaultMutableTreeNode treeRoot) {
File[] files = fileRoot.listFiles();
DefaultMutableTreeNode branchNode;
for (File f : files) {
if (f.isDirectory()) {
branchNode = new DefaultMutableTreeNode();
FileResourceUserObject branchObject = new FileResourceUserObject(branchNode);
branchObject.setExpanded(false);
branchObject.setText(f.getName());
branchObject.setResource(new FileResource(f.getName(), f.getAbsolutePath()));
branchObject.setBranchContractedIcon(openFolderImg);
branchObject.setBranchExpandedIcon(closeFolderImg);
branchNode.setUserObject(branchObject);
treeRoot.add(branchNode);
createTree(f, branchNode);
}
if (f.isFile()) {
branchNode = new DefaultMutableTreeNode();
FileResourceUserObject branchObject = new FileResourceUserObject(branchNode);
branchObject.setText(f.getName());
branchObject.setResource(new FileResource(f.getName(), f.getAbsolutePath()));
branchObject.setLeaf(true);
branchObject.setLeafIcon(fileImg);
branchNode.setUserObject(branchObject);
treeRoot.add(branchNode);
}
}
return;
}
}
FileResourceUserObject.java
public class FileResourceUserObject extends IceUserObject{
private FileResource resource;
public FileResourceUserObject(DefaultMutableTreeNode wrapper) {
super(wrapper);
}
public FileResource getResource() {
return resource;
}
public void setResource(FileResource resource) {
this.resource = resource;
}
}
FileResource.java
public class FileResource implements Resource{
private String filename;
private String fileAbsolutePath;
private String mimeType;
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
public FileResource(String filename, String fileAbsolutePath) {
this.filename = filename;
this.fileAbsolutePath = fileAbsolutePath;
this.mimeType = ec.getMimeType(filename);
}
#Override
public String calculateDigest() {
return filename;
}
#Override
public InputStream open() throws IOException {
return new FileInputStream(fileAbsolutePath);
}
#Override
public Date lastModified() {
return new Date();
}
#Override
public void withOptions(Options optns) throws IOException {
}
public String getFileAbsolutePath() {
return fileAbsolutePath;
}
public void setFileAbsolutePath(String fileAbsolutePath) {
this.fileAbsolutePath = fileAbsolutePath;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getMimeType() {
return mimeType;
}
}
UPDATE
What I noticed was that when I get the 500 Status Error the FileNotFoundException is always pointing to the same path java.io.FileNotFoundException: C:\SRC\dataFiles\998\validateFiles (Access denied)
I'm starting to think that all my FileResources are pointing to the same path... why is this happening?

There was a report of a bug on the IceFaces page where it says that using multiple outputResource tags had a strange behavior. See this link http://jira.icefaces.org/browse/ICE-3667
I think this was happening with I had the tree and many outputResource tags.
Moreover, I also read that using the outputResource tag it creates an Object at render time (or something like that I'm very new to JSF and all the stuff related) and it was memory-cpu consuming and it was better to use a servlet to perform the download. See http://www.dantoomeysoftware.com/pencils-down/2009/09/08/dont-use-icefaces-resource-for-download-use-a-download-servlet/
So it's better to implement a servlet, you can find useful info in http://balusc.blogspot.com/2007/07/fileservlet.html and (if your are new to all this stuff) Custom download servlet

Related

How to add dynamic jsf content (in a string) to JSF page [duplicate]

I am working on an application where I would like to include dynamic XHTML content from a stream. To handle this I wrote a taghandler extension which dumps the dynamic XHTML content to output component as
UIOutput htmlChild = (UIOutput) ctx.getFacesContext().getApplication().createComponent(UIOutput.COMPONENT_TYPE);
htmlChild.setValue(new String(outputStream.toByteArray(), "utf-8"));
This works fine for XHTML content which has no JSF tags. If I have JSF tags in my dynamic XHTML content like <h:inputText value="#{bean.item}"/>, then they're printed as plain text. I want them to render as input fields. How can I achieve this?
Essentially, you should be using an <ui:include> in combination with a custom ResourceHandler which is able to return the resource in flavor of an URL. So when having an OutputStream, you should really be writing it to a (temp) file so that you can get an URL out of it.
E.g.
<ui:include src="/dynamic.xhtml" />
with
public class DynamicResourceHandler extends ResourceHandlerWrapper {
private ResourceHandler wrapped;
public DynamicResourceHandler(ResourceHandler wrapped) {
this.wrapped = wrapped;
}
#Override
public ViewResource createViewResource(FacesContext context, String resourceName) {
if (resourceName.equals("/dynamic.xhtml")) {
try {
File file = File.createTempFile("dynamic-", ".xhtml");
try (Writer writer = new FileWriter(file)) {
writer
.append("<ui:composition")
.append(" xmlns:ui='http://java.sun.com/jsf/facelets'")
.append(" xmlns:h='http://java.sun.com/jsf/html'")
.append(">")
.append("<p>Hello from a dynamic include!</p>")
.append("<p>The below should render as a real input field:</p>")
.append("<p><h:inputText /></p>")
.append("</ui:composition>");
}
final URL url = file.toURI().toURL();
return new ViewResource(){
#Override
public URL getURL() {
return url;
}
};
}
catch (IOException e) {
throw new FacesException(e);
}
}
return super.createViewResource(context, resourceName);
}
#Override
public ResourceHandler getWrapped() {
return wrapped;
}
}
(warning: basic kickoff example! this creates a new temp file on every request, a reuse/cache system should be invented on your own)
which is registered in faces-config.xml as follows
<application>
<resource-handler>com.example.DynamicResourceHandler</resource-handler>
</application>
Note: all of above is JSF 2.2 targeted. For JSF 2.0/2.1 users stumbling upon this answer, you should use ResourceResolver instead for which an example is available in this answer: Obtaining Facelets templates/files from an external filesystem or database. Important note: ResourceResolver is deprecated in JSF 2.2 in favor of ResourceHandler#createViewResource().
My solution for JSF 2.2 and custom URLStream Handler
public class DatabaseResourceHandlerWrapper extends ResourceHandlerWrapper {
private ResourceHandler wrapped;
#Inject
UserSessionBean userBeean;
public DatabaseResourceHandlerWrapper(ResourceHandler wrapped) {
this.wrapped = wrapped;
}
#Override
public Resource createResource(String resourceName, String libraryName) {
return super.createResource(resourceName, libraryName); //To change body of generated methods, choose Tools | Templates.
}
#Override
public ViewResource createViewResource(FacesContext context, String resourceName) {
if (resourceName.startsWith("/dynamic.xhtml?")) {
try {
String query = resourceName.substring("/dynamic.xhtml?".length());
Map<String, String> params = splitQuery(query);
//do some query to get content
String content = "<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'> MY CONTENT"
+ "</ui:composition>";
final URL url = new URL(null, "string://helloworld", new MyCustomHandler(content));
return new ViewResource() {
#Override
public URL getURL() {
return url;
}
};
} catch (IOException e) {
throw new FacesException(e);
}
}
return super.createViewResource(context, resourceName);
}
public static Map<String, String> splitQuery(String query) throws UnsupportedEncodingException {
Map<String, String> params = new LinkedHashMap<>();
String[] pairs = query.split("&");
for (String pair : pairs) {
int idx = pair.indexOf("=");
params.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
}
return params;
}
#Override
public ResourceHandler getWrapped() {
return wrapped;
}
static class MyCustomHandler extends URLStreamHandler {
private String content;
public MyCustomHandler(String content) {
this.content = content;
}
#Override
protected URLConnection openConnection(URL u) throws IOException {
return new UserURLConnection(u, content);
}
private static class UserURLConnection extends URLConnection {
private String content;
public UserURLConnection(URL url, String content) {
super(url);
this.content = content;
}
#Override
public void connect() throws IOException {
}
#Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(content.getBytes("UTF-8"));
}
}
}
}

How to get file upload path location for database by setter and getter in jsf

I m having trouble to set value for entity bean. the problem is that when i populate form file will be upload but i need file path to store in data base. In my bean i have used setter of employee entity to set file url but And I think the code is enough to set file path for database but data is storing on database leaving employeePicture as null..
#Named
#RequestScoped
public class EmployeeAddController {
private Employees employees;
private String fileNameForDataBase;
private Part file;
#Inject
private EmployeeUpdateService updateService;
#PostConstruct
public void init() {
employees = new Employees();
}
public Employees getEmployees() {
return employees;
}
public void setEmployees(Employees employees) {
this.employees = employees;
}
public String getFileNameForDataBase() {
return fileNameForDataBase;
}
public void setFileNameForDataBase(String fileNameForDataBase) {
this.fileNameForDataBase = fileNameForDataBase;
}
public Part getFile() {
return file;
}
public void setFile(Part file) {
this.file = file;
}
public void upload() throws IOException {
ServletContext ctx = (ServletContext) FacesContext.getCurrentInstance()
.getExternalContext().getContext();
String realPath = ctx.getRealPath("/");
int random =(int) (Math.random() * 10000 + 1);
String fileString= realPath + File.separator + "resources/image/employee"+random+".jpg";
employees.setEmployeePicture(fileString);
try (InputStream input = file.getInputStream()) {
Files.copy(input, new File(fileString).toPath());
}
}
public String addEmployee() {
try {
this.updateService.add(employees);
return "index?faces-redirect=true";
} catch (Exception e) {
return null;
}
}
}
in My jsf page
"<div class="form-group">
<h:outputText value=" Employee Picture" class="col-sm-3 control-label"/>
<div class="col-sm-9">
<h:inputFile value="#{employeeAddController.file}">
<f:ajax listener="#{employeeAddController.upload()}"/>
</h:inputFile>
<h:outputText value="#{employeeAddController.fileNameForDataBase}"/>
</div>
<div>
<h:message for="fileUpload" class="text-primary"/>
</div>
</div>"***strong text***

Handle file download request in JSF 2.1 + PrimeFaces 5.1

I have a web application in JSF 2.1 + PrimeFaces 5.1 that has a datatable where I list records from a database. Each row can be expanded to show some details, and there I have a button to download a XML file that has its contents saved in the DB.
<p:dataTable id="event_queue_table_id" var="event" value="#{eventQueueBean.eventQueue}" rowKey="#{event.id}">
...
<p:rowExpansion>
...
<p:commandButton ajax="false" icon="ui-icon-arrowthick-1-s" actionListener="#{eventQueueBean.downloadXml(event.id)}">
<p:fileDownload value="#{fileBean.file}"/>
</p:commandButton>
</p:rowExpansion>
</p:dataTable>
I want to fetch the XML contents from the DB, create the file and prompt the user to open/save it. The bean that controls this datatable looks like this:
#ManagedBean
#ViewScoped
public class EventQueueBean implements Serializable {
#ManagedProperty(value="#{fileBean}")
private FileBean fileBean;
public void downloadXml(BigDecimal eventId) {
try {
logger.entry(eventId);
DtoGetXmlEvent dtoGetXmlEvent = null;
if (eventId != null) {
dtoGetXmlEvent = eventQueueService.getXmlEvent(eventId);
String xml = dtoGetXmlEvent.getXml();
if (xml == null) {
// show error message stating that file does not exist
} else {
this.fileBean.download(xml, eventId + ".xml", "application/xml");
}
}
logger.exit();
} catch (...)
}
}
}
And my FileBean is:
#ManagedBean
#ViewScoped
public class FileBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = LogManager.getLogger(FileBean.class);
private StreamedContent file;
public FileBean() {
logger.entry();
}
public void download(String content, String fileName, String contentType) {
logger.entry(fileName, contentType);
InputStream stream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
file = new DefaultStreamedContent(stream, contentType, fileName);
logger.exit();
}
public StreamedContent getFile() {
return file;
}
public void setFile(StreamedContent file) {
this.file = file;
}
When I try to download an empty XML (the DB retrieves NULL content), the open/save file prompt does not show, but if I try to refresh the page I get the "To display this page, Firefox must send information that will repeat any action (such as a search or order confirmation) that was performed earlier.". How can I avoid this?

Primefaces p:orderList java backing list does not update

I am currently implementing a orderable list using PrimeFaces' component, embedded inside a . I was able to get the list to appear properly with my items. However, when I saved the list and submitted it back to the server, the rearranged items did not get reflected in the backing bean for some reason. Since the Primefaces showcase was able to see the changes, what am I doing wrong?
XHTML Snippet:
<h:form id="confirmDialogForm">
<p:confirmDialog id="arrangeProjDialog" widgetVar="arrangeDlg" width="600"
header="Meeting Order"
appendToBody="true" message="Drag and drop to rearrange meeting order">
<p:orderList id="arrangeProjDialogList"
value="#{adminMeetingListBean.orderProjList}"
converter="#{adminMeetingListBean.rowConverter}"
var="po"
controlsLocation="left"
styleClass="wideList"
itemLabel="#{po.projectTitle}"
itemValue="#{po}"
>
<f:facet name="caption">Proposals</f:facet>
</p:orderList>
<p:commandButton value="Save" ajax="true" process="arrangeProjDialogList #this"
actionListener="#{adminMeetingListBean.updateProposalMeetingOrder}" onclick="arrangeDlg.hide();">
</p:commandButton>
<p:button value="Cancel" onclick="arrangeDlg.hide(); return false;" />
</p:confirmDialog>
</h:form>
Backing Bean:
public void updateProposalMeetingOrder() {
if (selectedMeeting != null) {
orderProjTitles.get(0);
meetingService.updateMeetingProjSequence(orderProjList, selectedMeeting.getMeetingId());
}
}
The List is a list of POJO "ProposalOrderRow" objects. This has the definition:
public class ProposalOrderRow implements Serializable {
private static final long serialVersionUID = -5012155654584965160L;
private int dispSeq;
private int appId;
private int assignmentId;
private String refNo;
private String projectTitle;
public int getDispSeq() {
return dispSeq;
}
public void setDispSeq(int dispSeq) {
this.dispSeq = dispSeq;
}
public int getAppId() {
return appId;
}
public void setAppId(int appId) {
this.appId = appId;
}
public String getRefNo() {
return refNo;
}
public void setRefNo(String refNo) {
this.refNo = refNo;
}
public String getProjectTitle() {
return projectTitle;
}
public void setProjectTitle(String projectTitle) {
this.projectTitle = projectTitle;
}
public int getAssignmentId() {
return assignmentId;
}
public void setAssignmentId(int assignmentId) {
this.assignmentId = assignmentId;
}
}
Converter:
#FacesConverter("proposalOrderRowConverter")
public class ProposalOrderRowConverter implements Converter {
private List<ProposalOrderRow> orderRows;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String newValue) {
if (newValue.isEmpty()) {
return null;
}
for (ProposalOrderRow item : orderRows) {
String refNo = item.getRefNo();
if (refNo.equals(newValue)) {
return item;
}
}
return null;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return "";
}
ProposalOrderRow row = (ProposalOrderRow) value;
String output = row.getRefNo();
return output;
}
public List<ProposalOrderRow> getOrderRows() {
return orderRows;
}
public void setOrderRows(List<ProposalOrderRow> orderRows) {
this.orderRows = orderRows;
}
}
This problem is caused by appendToBody="true" in the confirm dialog. Setting it to false solved the problem.
See link here: link

picklist PrimeFaces - How to get data from target-list?

I've created a picklist via PrimeFaces. Now i want to handle the selected items which are listed in the target list when i click the commandButton.
I want to pass the data through the controller and store them in my database. But everytime i call the function duallist.getTarget() it's empty.
I've crated a foreach-Loop where i want to select all items in the target list:
Controller (Bean):
private List<DTOAktivitaet> source = new ArrayList<DTOAktivitaet>();
private List<DTOAktivitaet> target = new ArrayList<DTOAktivitaet>();
private List<DTOAktivitaet> zwischen = new ArrayList<DTOAktivitaet>();
public void speicherAktiZug() {
DTOAktivitaet aktivitaet_vorgaenger = null;
for (DTOAktivitaet item : controller.getAktivitaeten()) {
if (item.toString().equals(selected)) {
aktivitaet_vorgaenger = item;
}
}
for (DTOAktivitaet aktivitaet : zwischen) {
try {
dao.aktiZugAkt(aktivitaet_vorgaenger, aktivitaet);
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public AktiListController() {
for (DTOAktivitaet ak : controller.getAktivitaeten()) {
source.add(ak);
}
aktis = new DualListModel<DTOAktivitaet>(source, target);
zwischen = aktis.getTarget();
}
JSF:
<h:form id="form" name="formular">
<h:outputText id="aktivitaet"
value="#{aktiListController.selected}" />
<p:pickList id="pickList" value="#{aktiListController.aktis}"
var="aktivitaet" itemValue="#{aktivitaet}"
itemLabel="#{aktivitaet}" converter="aktivitaetsConverter"
showSourceControls="true" showTargetControls="true" />
<h:commandButton
action="#{aktiListController.speicherAktiZug}"
value="Aktivität-Abhängigkeit anlegen" class="commandButton">
</h:commandButton>
</h:form>
Converter:
#EJB
public class AktiListConverter implements Converter {
private InitialisierungController controller = InitialisierungController
.getInstance();
DTOAktivitaet aktivitaet = new DTOAktivitaet();
String name = "";
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
for (DTOAktivitaet item : controller.getAktivitaeten()) {
if (item.toString().equalsIgnoreCase(arg2)) {
this.aktivitaet = item;
System.out.println(aktivitaet);
return aktivitaet;
}
}
return null;
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
this.aktivitaet = (DTOAktivitaet) arg2;
return this.name = aktivitaet.getTeambezeichnung();
}
}
My Problem: The target-List is empty before i want to store the items in my database.
I don't fully understand your code as it is not written in English but as far as I can see your Converter is written badly. As far as I can see you do a toString() and a fromString() basically. This is quite error prone and the way you did it, heavy in performance. It is a better idea to use unique ID's (business or database).
Example:
#FacesConverter(value = "aktiListConverter")
public class AktiListConverter implements Converter
{
private InitialisierungController controller = InitialisierungController.getInstance();
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2)
{
//Get object by it's unique ID
return controller.getById(Long.parseLong(arg2));
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2)
{
//Return object's unique ID
return ((DTOAktivitaet) arg2).getId();
}
}
In stead of using the object as itemLabel (which performs a toString()) use something that generates a nice label like getName() for a person.
itemLabel="#{aktivitaet.nameOrSomething}"
The speicherAktiZug() method doesn't really make sense to me so I came this far:
public class AktiListController
{
private List<DTOAktivitaet> source;
private List<DTOAktivitaet> target = new ArrayList<DTOAktivitaet>();
private DualListModel<DTOAktivitaet> aktis;
public AktiListController()
{
source = controller.getAktivitaeten();
aktis = new DualListModel<DTOAktivitaet>(source, target);
}
//Getters and setters
public void speicherAktiZug()
{
target = aktis.getTarget();
//target should contain the picked items here.
}
}
I see you are also using aktiListController.selected but I cannot see what it's used for.
Names of Conterter between (XHTML) and (Class Converter) is not equal.
converter="aktivitaetsConverter"
public class AktiListConverter implements Converter {...}

Resources