#ViewScope vs #RequestScope file download - jsf

I am using:
JSF: 2.2.13
Primefaces: 6.2
PROBLEM: When I make "ImageView" bean #ViewScoped then my file downloads after pressing the button. When I make "ImageView" bean #RequestScoped then my file doesn't download and the app simply opens a new page (the current page) without any URL params (so just opens http://localhost:8080/imageView.jsf)
SUSPECTED PROBLEM: Maybe <f:param> sends diffrent things depending if the ImageView is #ViewScoped vs #RequestScope
I open the page with the following GET REQUEST http://localhost:8080/imageView.jsf?contentFileId=1
I have the following code:
<h:form id="form">
<p:commandButton id="btn" value="Download"
icon="fa fa-download" ajax="false">
<f:param name="contentFileId" value="#{imageView.contentFileId}" />
<p:fileDownload value="#{streamedContentView.image}"/>
</p:commandButton>
</h:form>
The beans:
ImageView
#Named
#RequestScoped
public class ImageView implements Serializable {
private String contentFileId;
#PostConstruct
private void init() {
HttpServletRequest request = (HttpServletRequest) FacesContext
.getCurrentInstance()
.getExternalContext()
.getRequest();
contentFileId = request.getParameter("contentFileId");
}
//...GETTERS & SETTERS
}
StreamedContentView
#Named
#ApplicationScoped
public class StreamedContentView {
#Inject
ContentFileManager contentFileManager;
public StreamedContent getImage() throws URISyntaxException, IOException {
//Get id of file
FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> requestParameterMap = context.getExternalContext().getRequestParameterMap();
String rawContentFileId = requestParameterMap.get("contentFileId");
//Get file
ContentFile contentFile = contentFileManager.findById(Long.parseLong(rawContentFileId));
InputStream stream = new ByteArrayInputStream(contentFile.getContents());
return new DefaultStreamedContent(stream, contentFile.getMimeType(), contentFile.getFileName());
}
}

Related

JSF p:inputText is not coming in ManagedBean while file upload listener is called

I am using JSF 2.2.20. In the xhtml page, there is one input text field and a file upload (advanced mode) . But my problem is, while listener is called for file-upload, the input text is coming as empty. How can I get the input text? Help me out.
xhtml code snippet:
<h:form id="formID" enctype="multipart/form-data" method="post">
<p:growl id="growlId" sticky="true" showDetail="true"><p:autoUpdate /></p:growl>
<p:outputPanel id="DocInfo">
<h:panelGrid id="DocGrid" columns="3" style="margin-bottom:10px" cellpadding="8">
<p:outputLabel for="upload_Doc_Name" value="Document Name :* " />
<p:inputText id="upload_Doc_Name" value="#{uploadDocManagedBean.uploadDocName}" style="font-size:8pt;width:230px" />
<p:outputLabel for="projectUploadDocId" value="Choose File :* " style="font-weight:bold; float:left" />
<p:fileUpload id="projectUploadDocId" value="#{uploadDocManagedBean.uploadedFile}" mode="advanced" dragDropSupport="true"
listener="#{uploadDocManagedBean.fileUploadListener}" />
<br/>
</h:panelGrid>
</p:outputPanel>
</h:form>
The managed bean code snippet:
#ManagedBean(name = "uploadDocManagedBean")
#ViewScoped
public class UploadDocManagedBean implements Serializable {
private static final long serialVersionUID = -1L;
private String uploadDocName;
private UploadedFile uploadedFile;
public String getUploadDocName() {
return uploadDocName;
}
public void setUploadDocName(String uploadDocName) {
this.uploadDocName = uploadDocName;
}
public UploadedFile getUploadedFile() {
return uploadedFile;
}
public void setUploadedFile(UploadedFile uploadedFile) {
this.uploadedFile = uploadedFile;
}
public void fileUploadListener(FileUploadEvent fileUploadEvent) {
try {
uploadedFile = fileUploadEvent.getFile();
String filename = uploadedFile.getFileName();
if (uploadDocName == null || uploadDocName.isEmpty()) {
String msg = "Document Name is empty.";
FacesContext.getCurrentInstance().addMessage("growlId",
new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg));
return;
}
} catch (Exception e) {
e.printStackTrace();
}
}
In the managed bean, the uploadDocName is the coming as empty everytime, while this fileUploadListener() method is called.
What am I missing here?
You can define process attribute on fileUpload. To make it simple, try with process="#form", it should work ;) By default, only fileUpload client id e.g #this is sent to the server for processing
More details for fileUpload component, see here: https://primefaces.github.io/primefaces/11_0_0/#/components/fileupload

p:inputText inside ui:repeat works only for last element

I am creating an image gallery with JSF and PrimeFaces. I am using ui:repeat with p:graphicImage inside to display a list of images retrieved from db. Every image has an on click p:dialog (with its respective id) defined also inside ui:repeat. In the p:dialog I am showing again the clicked image and there is also a h:form that has inside a p:inputText and a p:commandbutton to save the text of p:inputText to a String property of a bean. The problem is that only last image of the list showed by ui:repeat "sees" the bean and set the property. If in the dialog of last image showed by ui:repeat I write a comment and click the commandbutton it sets the String text of the bean, if I do the same for the other images the String text is null. Maybe it's a problem of bean visibility. I tried to use different scopes for the bean but it doesn't work anyway.
This is the JSF code:
<ui:repeat value="#{imageShowController.images}" var="img">
<h:outputLink value="javascript:void(0)"
onclick="PF('picDialog-#{img.id}').show();">
<p:graphicImage value="#{imageShowController.streamedContent}"
width="250" height="250" cache="false">
<f:param name="id" value="#{img.id}" />
</p:graphicImage>
</h:outputLink>
<p:dialog id="picDialog-#{img.id}" widgetVar="picDialog-#{img.id}"
width="500" height="500">
<p:graphicImage value="#{imageShowController.streamedContent}">
<f:param name="id" value="#{img.id}" />
</p:graphicImage>
<h:form>
<h:panelGrid columns="2" cellpadding="5">
<p:inputText value="#{imageShowController.txt}" />
<p:commandButton value="Submit comment"
action="#{imageShowController.saveComment()}">
<f:param name="id" value="#{img.id}" />
</p:commandButton>
</h:panelGrid>
</h:form>
</p:dialog>
</ui:repeat>
This is the bean (Java):
#ManagedBean
#RequestScoped
public class ImageShowController {
#Inject
private UserSessionBean userSession;
#Inject
private ImageDaoService imagedao;
#Inject
private CommentDaoService commentdao;
private List<Image> images;
private String text;
private String id;
#PostConstruct
public void init() throws SQLException {
images = new ArrayList<>();
images = imagedao.findImagesByUserId( userSession.getUserId() );
}
public void saveComment(){
FacesContext context = FacesContext.getCurrentInstance();
String id =
context.getExternalContext().getRequestParameterMap().get("id");
Comment comment = new Comment();
comment.setText(text);
comment.setDate(new Date());
comment.setImage(imagedao.findById(Long.valueOf(id)).get(0));
commentdao.addComment(comment);
}
public StreamedContent getStreamedContent() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return new DefaultStreamedContent();
}
else {
id =
context.getExternalContext().getRequestParameterMap().get("id");
System.out.println("INDEX: "+id);
byte [] b = null;
for (int i = 0; i < images.size(); i++) {
if(images.get(i).getId() == Long.valueOf(id)){
b = images.get(i).getPicture();
break;
}
}
return new DefaultStreamedContent(new ByteArrayInputStream(b));
}
}
}
I solved using tag c:forEach of JSTL instead of ui:repeat. It works!!

Pass parameter to bean associated with PrimeFaces Dialog Frameworks' dialog

I have a template with button which opens dialog:
<p:commandButton
id="roles-button"
icon="fa fa-key">
<f:setPropertyActionListener value="#{user}" target="#{userAdministrationView.selectedUser}" />
<f:actionListener binding="#{userAdministrationView.openUserRolesDialogWithParameters()}"/>
<p:ajax
event="dialogReturn"
listener="#{dialogHandler.showMessage}"
update=":user-administration-form:user-administration-table"
global="false"
/>
</p:commandButton>
Backing bean for template (userAdministrationView) is #ViewScoped.
I want to pass parameter selectedUser to the dialog. Is it possible with using Faces.setContext/Request/FlashAttribute, like adviced here? I tried to implement it like:
public void openUserRolesDialogWithParameters() {
Faces.setContextAttribute("user", selectedUser);
dialogHandler.openDialog("user-roles-dialog");
}
and in dialogs backing bean (which is #ViewScoped too):
#PostConstruct
public void init() {
this.user = Faces.getContextAttribute("user");
...
}
but I get null in user. The same result is with setRequestAttribute and setFlashAttribute.
Here it is suggested to create #SessionScoped bean with properties, but this decision looks not very relevant for me. Is it the only way?
Thanks to BalusC, i started to search in right direction, and I found this explanation.
So, it works like this:
template backing bean :
public void openUserRolesDialogWithParameters() {
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
sessionMap.put("user", selectedUser);
dialogHandler.openDialog("user-roles-dialog", "contentWidth", "500");
}
dialog backing bean:
#PostConstruct
public void init() {
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
this.user = (UserModel) sessionMap.get("user");
sessionMap.remove("user");
...
}

Send p:autoComplete value as a param in JSF

i have a rare situation in my page i have a "p:autoComplete" which is bind to a backing bean i can read that auto complete item form the backing bean.
but the problem is the selected value from that auto complete need to be passed as a parameter, when user pressed the button, with some other parameters. which i really don't know how to do it?
this is my page which has the autocomplete
<p:panel header="Employee sales" style="width:500px"
toggleable="true" toggleSpeed="500" closeSpeed="500">
<p:autoComplete id="user_auto_complete"
value="#{salesReportMainController.userFromAutoComplete}"
completeMethod="#{salesReportMainController.completeUser}"
var="user" itemLabel="#{user.userName}" itemValue="#{user}"
converter="#{userConverter}" forceSelection="true" />
<p:commandButton id="Search" value="Generate"
action="admin_common_barchart">
<f:param name="todaysDate"
value="#{salesReportMainController.todaysDate}" />
<f:param name="beforDate"
value="#{salesReportMainController.dateBeforOneYear}" />
<f:param name="employeeName"
value="#{salesReportMainController.userFromAutoComplete.userName}" />
</p:commandButton>
</p:panel>
and this is the backing bean that binds to that page
#ViewScoped
public class SalesReportMainController implements Serializable{
private static final long serialVersionUID = 1L;
#ManagedProperty(value = "#{userService}")
public UserService userService;
public DateTime todaysDate;
public DateTime dateBeforOneYear;
public DateTime dateBeforsixMonths;
public List<User> allUsers;
public List<User> acFilterdUsers;
public User userFromAutoComplete;
#PostConstruct
public void init(){
int oneYear = ConstantConfiguration.YearsInMonths.ONE_YEAR.getValue();
int sixMonths = ConstantConfiguration.YearsInMonths.SIX_MONTH.getValue();
todaysDate = new DateTime();
dateBeforOneYear = new DateTime(todaysDate).minusMonths(oneYear);
dateBeforsixMonths = new DateTime(todaysDate).minusMonths(sixMonths);
}
// public String buttonClick(){
// System.out.println("aaaaaaaa");
// return null;
// }
public List<User> completeUser(String query) {
allUsers = userService.getAllUsers();
acFilterdUsers = new ArrayList<User>();
for (User user : allUsers) {
if(user.getUserName().toLowerCase().startsWith(query)){
acFilterdUsers.add(user);
}
}
return acFilterdUsers;
}
public String getAutoCompleteUser() {
if (userFromAutoComplete != null) {
//i can get the value of the selected item form auto complete
}
return null;
}
//getters and setters
}
and this is the page that i want to load
<h:form id="common_chart_form" prependId="flase">
<p:growl id="growl" showDetail="true" autoUpdate="true"
sticky="false" />
<p:outputLabel id="labelvalue" value="aaaaaaaaaa"/>
<p:chart id="chart" type="bar"
model="#{commonChartController.barModel}" style="height:600px" />
<p:commandButton value="Print" type="button" icon="ui-icon-print">
<p:printer target="chart" />
</p:commandButton>
<p:commandButton value="Back" action="admin_sales_reports" />
</h:form>
and this the backing bean of the above page
#Component
#ManagedBean
#RequestScoped
public class CommonChartController implements Serializable{
private static final long serialVersionUID = 1L;
#ManagedProperty(value = "#{orderService}")
public OrderService orderService;
#ManagedProperty(value = "#{userService}")
public UserService userService;
List<MonthSales> salesList;
private BarChartModel barModel;
#PostConstruct
public void init() {
String dateTo = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("todaysDate");
String dateFrom = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("beforDate");
String employeeName = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("employeeName");
System.out.println("user Name : "+employeeName);
if(employeeName != null && !employeeName.equals("")){
User user = userService.getUserByUserName("admin");
salesList = orderService.getMonthlySalesByUserName(UserUtility.stringDateToJodaDateTime(dateFrom).toDate(), UserUtility.stringDateToJodaDateTime(dateTo).toDate(), user);
createBarModel(salesList, user);
}else {
salesList = orderService.getMonthlySales(UserUtility.stringDateToJodaDateTime(dateFrom).toDate(), UserUtility.stringDateToJodaDateTime(dateTo).toDate());
createBarModel(salesList);
}
//
// salesList = orderService.getMonthlySales(UserUtility.stringDateToJodaDateTime(dateFrom).toDate(), UserUtility.stringDateToJodaDateTime(dateTo).toDate());
// createBarModel(salesList);
}
}
i can read the "dateTo" param and "dateFrom" param. problem is "employeeName" param is alwayas null

how to merge a shop entity to a client entity (many to one) in jsf

I'm trying to merge an existing shop to a new client in jsf but it isn't successful. The program consists basically off a backing bean controller,an ejb and the jsf page (register) I have been able to populate the shoplist in a comboBox UI. here is the code.
register.xhtml:
clientcontroller.client.fname is a SFSB.
Property already persisted but trying to be merged.
A shop from a list (shopcontroller.shopList)
<h:form>
<h:panelGrid columns="3" >
<h:outputText value="Select From.
Available Shops :" />
<h:selectOneMenu value="#.
{shopController.shop}" >
<f:selectItems var="s" value="#.
{shopController.shopList}" />
</h:selectOneMenu>
<h:commandButton value="register".
action="#{clientcontroller.Register(s)}" />
</h:panelGrid>
</h:form>
backing bean class:
ManagedBean(name="clientcontroller")
#RequestScoped
public class clientController {
#EJB ClientEJB clientEJB;
private Client clt = new Client();
private Shop shp = new Shop();
private String clientfname;
//getters and setters
public String Register(Shop shp){
this.shp = shp;
clientEJB.register(clt, shp);
return "";
}
EJB class:
#Stateful
#LocalBean
public class ClientEJB {
#PersistenceContext
EntityManager em;
public void addClient(Client clt){
em.persist(clt);
}
public void register(Client c ,Shop s){
c.getShopList().add(s);
s.setAvailability("false");
s.setClientid(c);
em.merge(s);
em.merge(c);
}
}
Adjust your code as follows:
XHTML:
<h:commandButton value="register" action="#{clientcontroller.Register}" />
ManagedBean
public String Register(){
clientEJB.register(clt, shp);
return "";
}
See Also:
JSF 2 dropdown box example

Resources