I have this situation: I am trying to remove an old avatar image for a user before putting a new one from the managed bean.
String fileName = "resources/img/useravatars/" + getSessionBean().getSearchAccount().getAvatar();
File f = new File(fileName);
I've googled a bit and it seems that I can get a path to that folder from ExternalContext like:
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.getExternalContext(). ...
But I couldn't find an appropriate method from class docs. Could you please help with what to put instead of ... or suggest a better solution.
PS. Somehow, I suspect it is possible to hardcode the link, but no luck so far.
I understand that the file is embedded in the WAR and that you're looking for the ExternalContext#getRealPath() method to resolve it based on a web-relative path. As per the Javadoc, this method is introduced in JSF 2.0 and does not exist in JSF 1.x. You seem to be using JSF 1.x, otherwise you wouldn't have asked this question. You need to use ServletContext#getRealPath() instead (which is also what the new JSF 2.0 method is delegating to, under the covers).
String relativeWebPath = "/resources/img/useravatars/" + ...;
ServletContext servletContext = (ServletContext) externalContext.getContext();
String absoluteDiskPath = servletContext.getRealPath(relativeWebPath);
File file = new File(absoluteDiskPath);
// ...
However, there's a big BUT: you can and should not write to the expanded WAR. Deleting files is also writing. Whenever you redeploy the WAR or restart the server, every change will be reverted and the expanded WAR will retain its initial state, hereby losing all changes made in the expanded WAR since the last deploy.
You really need to store those files in an external location whose root location can then be hardcoded or definied in some external configuration (properties) file. This way you can use java.io.File stuff the usual way.
There are several ways to serve files from an external location. You can find them all in the answer of the following question: Load images from outside of webapps / webcontext / deploy folder using <h:graphicImage> or <img> tag
Related
We have an application (Mojarra 2.3) where a user can change a global filter of the data it sees. When that happens, I want to keep the session, but invalidate the active views (which are server side).
I found this question which enables you to count the number of views: How do I count the number of views in a user's JSF session (JSF 2.2)?
Based on that I figured I could remove the attribute in which the views are stored. I came up with this method:
public static void invalidateViews() {
final HttpSession session = Faces.getSession();
List.of("com.sun.faces.application.view.activeViewContexts",
"com.sun.faces.application.view.activeViewMaps",
"com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap",
"org.jboss.weld.context.ConversationContext.conversations")
.forEach(session::removeAttribute);
Faces.redirect(Faces.getRequest().getRequestURL().toString());
}
The com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap was mentioned in the linked question's answer. I kind of guessed that it would not hurt to remove the other attributes. The answer also mentions that it is Mojarra only.
It seems to work so far, but I would like to ask this: should one clear server side views like this? And, if so, how can I support MyFaces as well?
It seems to work so far, but I would like to ask this: should one clear server side views like this?
Given that there is no standard API call for this, this is about the best you can do, yes. I have during the JSF 2.3 work requested for a more specific variant of this functionality to exist in the standard API because I needed to be able to destroy view scoped beans associated with a specific JSF view state (for the OmniFaces view scope unload functionality, see Hacks#removeViewState()). But this has unfortunately not yet been fleshed out because of difficulties with Portlets.
And, if so, how can I support MyFaces as well?
As seen in the OmniFaces Hacks helper class, the session attribute key for MyFaces 2.x is org.apache.myfaces.application.viewstate.ServerSideStateCacheImpl.SERIALIZED_VIEW and 4.x org.apache.myfaces.application.viewstate.StateCacheServerSide.SERIALIZED_VIEW.
By the way,
Faces.redirect(Faces.getRequest().getRequestURL().toString());
this is shorter:
Faces.refreshWithQueryString();
In our project I need to make a server side validation of an uploaded file (e.g. to prevent the upload of a "fake" file with an allowed extension). On the client side I've already done it using allowTypes param of p:fileUpload but i need this additional further control.
I've already tried by extending Primefaces' FileUploadFilter but I'm still not able to access the actual file uploaded from MultipartRequest: I can only access all the form fields instead.
Enumeration params = multipartRequest.getParameterNames();
I can probably access the file via reflection but I don't think it's a safe and "right" thing to do.
The best option to me is to override FileUploadRenderer but it's seem a bit too much just to add an additional check all over my application.
We are using Primefaces 3.5, but we're okay to upgrade to a newer version if this featuer is available in newer ones.
Any idea on what can/should I do to make this control happens ?
edit: I can add a FileUploadListener to all my controllers that manage views in which there's a p:fileUploadbut I was wondering if there's a way to intercept ALL the Multipart request and validate my item in there.
In your backing bean, you can take care for validation like this
long size = uploadedFile.getSize();
String content = uploadedFile.getContentType();
InputStream stream = uploadedFile.getInputStream();
byte[] contentBytes = new byte[(int) size];
stream.read(contentBytes);
String base64String = Base64.encodeBase64String(contentBytes);
if(content .... is not)
I'm missing something. In Eclipse I drafted a class to make PDF and imported a couple of fonts into a the package and accessed them like this:
Font garamondBlue = FontFactory.getFont("/fonts/Garamond.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
I'm moving this to an XPage bean now, and I can't find how to get them the same way. I could put them in as file resources, but how do I access them there?
I added images to classic Java agents back in the pre-XPage days, can we do something like that with a bean?
Thanks,
Brian
You can read file resources as input streams like this:
InputStream fileResource = FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream("filename");
I am stuck and need outside help from JSF experts with the following problem:
I defined some converters in the faces-config.xml for specific classes so I don't have to use the converter-attribute or tag all the time. For example:
<converter>
<converter-for-class>org.joda.time.DateTime</converter-for-class>
<converter-class>com.example.converter.JodaDateTimeConverter</converter-class>
</converter>
Now there is the need for a crawler for a JSF-Component (mostly rich:extendedDataTable) which builds the whole component tree and converts level after level into CSV, HTML or whatever might be needed later on. Namely a generic way to export to CSV, HTML, ... without the need to implement it every single time anew. It is almost done (thanks to the great idea of an old colleague of mine) and it does work great except for one part:
Object expressionResult = expression.getValue(FacesContext.getCurrentInstance().getELContext());
expressionResultString = expressionResult.toString();
That command retrieves the value of an h:outputText and converts it to String. That last line is what I want to replace with the converter-for-class if there is a custom converter for a specific expressionResult. I can't find out how to find that exact converter for my classes (as specified by faces-config). The FacesContext doesn't seem to hold any useful method/object for my use case. Accessing the faces-config.xml directly seems kind of wrong. A correct approach might look something like:
Converter converter = magically_fetch_the_correct_converter_for_expressionResult_type;
converter.getAsString(FacesContext.getCurrentInstance(), component,
expressionResult);
It would be fairly easy if I used converter-id and the appropriate attribute/tag for the components themselves but I really want to avoid that kind of useless additional code.
Can someone out there please help me?
You're looking for Application#createConverter().
Object object = expression.getValue(context.getELContext());
Class<?> type = expression.getType(context.getELContext());
Converter converter = context.getApplication().createConverter(type);
String string = converter.getAsString(context, component, object);
I would like to have a dynamic resource bundle in my application. I will show a form to the user where he can edit the value of Resource Bundle. I can’t restart my application for this changes take effect. I found a solution that solves part of my problem. Using “commons-configuration” from Apache or/and this http://www.coderanch.com/t/292347/JSP/java/we-reload-property-file , i could change my “.properties” file and get the results using “ResourceBundle.getBundle” .
The problem is when I try to access the property in my XHTML file like this:
<h:outputLabel value="#{msg[user.name]}" />
The value of this key is out of date.
Is there a solution for this?
Just for info, I am using spring, so I have this in my faces-config:
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
But I don’t think this is the problem. Anyway, another solution would be to use a session bean and get the property values accessing it.
What do you think about it? Would be better store this values in my database and forget about the properties file?
\o/
I have tested to move my resource bundle definition from my faces-config to my page using tag f:loadBundle and it worked!