Custom download servlet - jsf

I looked into BalusC's code for a custom download servlet from absolute path (see http://balusc.blogspot.com/2007/07/fileservlet.html#FileServletServingFromAbsolutePath). I'm not a Java Web Developer Expert so I would love if someone can explainme this part of the code
private String filePath;
// Actions ------------------------------------------------------------------------------------
public void init() throws ServletException {
// Define base path somehow. You can define it as init-param of the servlet.
this.filePath = "/files";
// In a Windows environment with the Applicationserver running on the
// c: volume, the above path is exactly the same as "c:\files".
// In UNIX, it is just straightforward "/files".
}
When does the init method gets called? Why do we need the filePath to be set in the init method?
I have an XHTML (Mojarra+IceFaces) with something like the code below that works great. My page is missing just the part of downloading the file which is referenced by the outputLink tag
<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:outputLink value="#{item.userObject.filePath}">
<ice:outputText value="#{item.userObject.fileName}"/>
</ice:outputLink>
</ice:panelGroup>
</f:facet>
</ice:treeNode>
</ice:tree>
In my Backing bean I have two fields fileName (just the name of the filewith extension e.g. Image.jpeg) and filepath (the ABSOLUTE path of the file in the server). Finally I want to download the file with the custom servelet, how can I do that??
Cheers,
UPDATE
Let's say mi base-dir is /SRC and under that dir I have all my xhtml pages and the WEB-INF and META-INF and aditionally I have a dir called dataFiles under dataFiles I have the following structure
--dataFiles
|----Enterprise1
| |--User1
| | |--goodFiles
| | | |--ok.txt
| | |--badFiles
| | |--bad.txt
| |--User2
| | |--goodFiles
| | | |--ok.txt
| | |--badFiles
| | |--bad.txt
|----Enterprise2
|--User1
| |--goodFiles
| | |--ok.txt
| |--badFiles
| |--bad.txt
|--User2
|--goodFiles
| |--ok.txt
|--badFiles
|--bad.txt
that's how I render the tree with IceFaces and I just have the filename in the backing bean (i.e. ok.txt or bad.txt) but I cannot figure out how to download the file pointing by the link in the tree.

Well finally got it work.
First of all thanks to BalusC, there were some posts here that helped me understand but someone delete them. Anyway, here's what I've learned.
In Servlet's init method the filePath variable must point to the absolute path where the files to download are.
In the web.xml the servlet-map-url-pattern will cause to execute the servlet when the browser has that url pattern.
In the xhtml page tha value of the link should begin with the url-pattern followed by the name (or a path+FileName) so when you click the link the download begins.
That's all I had to do !
In the example of the question, the filePath variable in the servlet's init method will point to the absolute path, something like C:\myApp\dataFiles
Then in the xhtml will call the servlet with something like
<ice:outputLink value="dl/myPath/#{myBean.fileName}>
<ice:outputText value="#{myBean.fileName}"/>
</ice:outputLink>
Note 1: that the first part of the value of the outputLink is dl/ this is because the url-pattern for the servlet to download is mapped to it
Note 2: in the outputLink the value of myPath could be dl/Enterprise1/User1/file1.ext
Cheers

Related

JSF h link takes last item in list instead of current

I got a list of objects displayed in a page.
This is the view:
<h:form>
<h:dataTable var="o" value="#{opleidingController.opleidingen}" border="0" >
<h:column>
<f:facet name="header">Code</f:facet>
<h:link value="#{o.opl_code}" outcome="#{opleidingController.getOpleidingByCode(o.opl_code)}" />
</h:column>
<h:column>
<f:facet name="header">Titel</f:facet>
<h:outputText value="#{o.opl_titel} "></h:outputText>
</h:column>
<h:column>
<f:facet name="header">Thema</f:facet>
<h:outputText value="#{o.opl_thema} "></h:outputText>
</h:column>
</h:dataTable>
</h:form>
This displays everything very well.
Like you can see I got the code part of the object set as a link.
With this code I get an object out of the database, from which I display the details.
The problem here is that every link displays the details of the last object of the list instead of the current object where I click the link.
This is the function I call (which works):
public String getOpleidingByCode(String code) {
this.opleiding = this.opleidingFacade.getOpleidingByCode(code);
return "details";
}
I hope any of this makes any sense?
Sorry if the solution is super clear but I am new to all of this.
Thanks in advance!
Kind regards
Deflandrex
EDIT:
This is the function that I use to call the first view (from which I provided the code)
public String getOpleidingenOpThema() {
this.opleidingen = this.opleidingFacade.getOpleidingenOpThema();
return "resultaat";
}
Both the functions are located in 1 controller.
What happens with the current code :
The outcome value is processed for each link element in the datatable sequentially by calling the opleidingController. getOpleidingByCode(o.opl_code). The backing bean method sets the this.opleiding value corresponding to the o.opl_code. Once all the links's outcome values are processed this.opleiding holds the value of the last o.opl_code. Hence, you are seeing last value from the list in the details page.
One Proposed solution:
The this.opleiding value should be set in the controller based on the o.opl_code when you process the details after clicking the link and not when the link is displayed and the outcome is set. You need to
Set outcome="details" in the h:link tag as this value is static and does not change based on any logic in the backing bean and remove method binding.
Pass the value of o.opl_code as a request parameter to the link as given below within the h:link tag.
<f:param name="opl_code" value="#{o.opl_code}"/>
Have the detail backing bean load the this.opleiding value based on the request parameter opl_code. This way you will have details for specific opl_code based on what link you click.

How can I add attributes to components which don't have their own renderers using the f:attribute component?

I want to write a custom renderer for the h:selectOneMenu component and eventually make use of the description property of the UISelectItem class to add a title a.k.a. tooltip to f:selectItems following BalusC's profound guides in https://stackoverflow.com/a/25512124/3280015 and http://balusc.blogspot.de/2008/08/styling-options-in-hselectonemenu.html.
Now I did extend the com.sun.faces.renderkit.html_basic.MenuRenderer in my own CustomMenuRenderer, registered it with the faces-config.xml and overrode the renderOption method, adding the following code before option tag is terminated by the Responsewriter:
String titleAttributeValue = (String) component.getAttributes().get("title");
if (titleAttributeValue != null) {
String indexKey = component.getClientId(context)
+ "_currentOptionIndex";
Integer index = (Integer) component.getAttributes().get(indexKey);
if (index == null) {
index = 0;
}
component.getAttributes().put(indexKey, ++index);
}
I'm not quite sure I'm doing the indexKey thing right or whether I need it for the title attribute or should use a writer.writeAttribute("title", titleAttributeValue, null); instead because I don't have a list like in the optionClasses tutorial, but the code works so far!
In the actual view definition use case I did:
<h:selectOneMenu value="#{cc.data}">
<f:attribute name="title" value="outerTEST" />
<c:forEach items="#{cc.list}" var="val">
<f:selectItem value="#{val}" itemValue="#{val}" itemLabel="#{val.label}">
<f:attribute name="title" value="innerTEST #{val.description}" />
</f:selectItem>
</c:forEach>
</h:selectOneMenu>
(I just put the #{val.description} there in the title value to clarify my intention, it is currently still empty and I will have to think about how to populate it per element later, but for the sake of the question we can assume it is already filled.)
But now I'm getting the "outerTEST" properly showing up in the title attribute of the option in the resulting XHTML in the Browser, yet I'm not seeing any of the "innerTEST" which would and should be individual per selectItem and which is what this is eventually all about.
I understand the f:selectItem and f:selectItemscomponents do not have their own renderers but rendering of options is generally handled by the MenuRenderer via its renderOption method.
But how then would I add individual titles to the individual selectItems??
Thanks

primefaces dynamic tab render

I have some tabs and rendered attiributes. My problem is how can i set this tab's rendered attiributes to false when i close the tab. I set with setRendered method but the problem is renderTab1 variable still holds True. What i want to do is; setting renderTab1 variable to "False". By the way i have many tabs like 20-25. If you have any better solution you can share.
my xhtml;
<p:ajax event="tabClose" listener="#{myController.onTabClose}"/>
<p:tab id="firstTab" closable="true"
rendered="#{myController.renderTab1}"/>
my tabclose method;
public void onTabClose(TabCloseEvent event) {
event.getTab().setRendered(false);
}
I was find a solution and i need to did this to solve my problem.
My solution not only did with rendered, i needed to use one variable to render tab, and one to send you to position that will be my tab inside of my tabView
some like this.
in the tabView set parameters like this...
<p:tabView id="idTabView" widgetVar="tabView" dynamic="true" cache="false">
in tab
<p:tab rendered="#{mb.valiable == 1}"><!--the number 1 is an example-->
</p:tab>
</p:tabView>
On commandButton where i suppose is on the first tab i put this:
<p:commandButton
actionListener="mb.activeTab()"
update="#form"
oncomplete="PF('tabView').select(1);" <!--this line send to tab that you are rendering with your flag in mb "variable" if you are render TAB in position three you need to put PF('tabView').select(2);-->
on my MAnagedBean method:
mb{
private int valiable;
public voi activeTab(){
setValiable(1);
}
//setter y getters
}
i hope help you my solution.
regards
The rendered property of a JSF component is resolved multiple times throughout the JSF lifecycle, so setting it manually on an event is unlikely to work by the time JSF actually begins rendering. The rendered attribute however can take the following values:
A boolean property: Eg. rendered="#{myController.booleanProperty}"
A method that returns a boolean: Eg. rendered="#{myController.doStuffAndReturnBoolean()}"
An EL expression that resolves to a boolean value: Eg. rendered="#{myController.intValue gt 3}"

JSF t:messages - How to avoid tables?

I got JSF Tomahawk messages and those messages got rendered as one HTML-Table. How do I avoid such tables? I would prefer one div for all messages which contains one paragraph for each message. Thanks in advance.
My JSF-file-snippet:
<t:messages layout="table" replaceIdWithLabel="true" showDetail="true" showSummary="false" styleClass="mycustomclasswhichgrabsthisshit" />
Check the Tomahawk tag documentation. The <t:messages> tag documentation says the following:
Name | Type | Supports EL? | Description
-------+--------+--------------+---------------------------------------------
layout | String | Yes | The layout: "table" or "list". Default: list
So, fix it accordingly:
<t:messages layout="list" ... />
Or just remove it altogether. It's the default already.
You can if necessary remove the list bullets using CSS:
.mycustomclasswhichgrabsthisshit {
list-style-type: none;
}
(disclaimer: the ranty classname is literally copied from your example, it's not mine)

How to add new line Character ( \n ) in message resource bundle in JSF1.2

In my sample JSF application am using rich:dataTable in page to display data.
I have 2 header to display value in rich:dataTable like following
--------------------------------
| UserDetails | EmpoyeeDetails |
--------------------------------
In message resource bundle file having key and value like
usrDet = UserDetails
empDet = EmpoyeeDetails
I need to display like User in one line and Details in next line of that particular header
----------------------
| User | Empoyee |
| Details | Details |
---------------------
How to add new line character in message bundle between words? I tried by adding Hexadecimal code, Numerical Code for \n like
, \u000A but its not
working for me! Any Idea?
JSF generates HTML. Newlines in HTML are not represented by the \n character, but by the <br> element.
In order to have the HTML client to interpret \n too, you need to throw in CSS white-space: pre or pre-wrap:
key = Lorem ipsum.\nDolor sit amet.
<h:outputText value="#{bundle.key}" style="white-space: pre-wrap" />
Alternatively, use <br> instead and have JSF unescape it. E.g.
key = Lorem ipsum.<br/>Dolor sit amet.
<h:outputText value="#{bundle.key}" escape="false" />
Try the steps outlined here: http://www.mkyong.com/java/how-to-insert-a-new-line-in-resource-bundle-messages-java/
Basically, you use the StringEscapeUtils.unescapeJava(String str) static method.

Resources