JBoss equivalence of glassfish alternate docroot - jsf

This is very easy using Glassfish:
Consider my absolute path on unix /apps/static_content/.
Using Glassfish, I will simply define alternate doc root as:
<property name="alternatedocroot_1"
value="from=/static/* dir=/apps/static_content/"/>
When I upload my images and other data files, I can save them to the /apps/static_content directory, and within my JSF page I can display my static content normally as:
<p:graphicsimage value="/static/external_web_app.png"/>
I really need to achieve the same functionality in JBoss AS7
How can I do this?

This question is a little bit old, but answering if someone need to do this with newer versions of JBoss/Wildfly.
JBoss AS was renamed to Wildfly from version 8 (i.e. Wildfly 8 is JBoss AS 8) and Red Hat supported version of JBoss was renamed to JBoss EAP. So this applies to:
Wildfly (any version)
JBoss EAP (from version 7)
First thing to note is that "Alternate doc root" feature in glassfish doesn't work like that. Please take a look at this question for an explanation of the behavior of this feature: Alternate docroot not working on glassfish 4
Now, to answer this question, JBoss/Wildfly is build upon Undertow, that let you do exactly what you need. Refer at this question on how to configure undertow as a web server for static content: How to configure Wildfly to serve static content (like images)?

Option 1: You could try to deploy a separate exploded .war file, and use that for your static content
In your case: In .../jboss-7/standalone/deployments/ there must be a static.war/.
So the uploads go into this directory, and the content is served back the normal way.
As for details, see Is it possible to deploy an exploded war file (unzipped war) in JBoss AS 7
As pointed out by BalusC: You must not redeploy/remove this directory, as soon as data has been uploaded. You should have a regular backup of this directory.
As far as I know this is the only possibility to do it by configuration/setup only.
Option 2: Create separate webapp with name static.war. Add a servlet to stream the static content
This way there is no need to upload/store the files into the file system below ../deployments/, it could be any directory, but you need an additional servlet, so it's solved programatically.
A simple streaming servlet could look like this (just streaming - no authentication etc.):
public class DownloadServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
final File dir = new File("/var/cms/storage/");
final String start = "/static/";
final String relativePath = request.getRequestURI().substring(
request.getRequestURI().indexOf(start) + start.length());
final File file = new File(dir, relativePath);
final String ct = URLConnection.guessContentTypeFromName(file.getName());
response.setContentType(ct);
final InputStream is =
new BufferedInputStream(new FileInputStream(file));
try {
final boolean closeOs = true;
org.apache.commons.fileupload.util.Streams.copy
(is, response.getOutputStream(), closeOs);
} finally {
is.close();
}
}
Map all URLs to this servlet:
<servlet-mapping>
<servlet-name>DownloadServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
The name static.war provides the /static/ web context, so that should make it compatible with the URLs in your code.

If you explore jboss directory you will find that there are many you can use to store different type of data like jboss.serer.data.dir .
You can try asking this directory path via system properties and store in a folder the data your services are using, under such directory.
String path = System.getProperty("jboss.server.data.dir");
Then you can use path as you want, if is just static as shown in your example you set directly the name of the directory.
This should work, I hope :p
ps: as the previous answer suggest the saved data will keep in the directory, and you must not redeploy/remove this directory.. It will keep your data there..

Related

How to upload file using JSF 2.2 <h:inputFile>? Where is the saved File?

I would like to be able to upload files in my JSF2.2 web application, so I started using the new <h:inputFile> component.
My only question is, how can I specify the location, where the files will be saved in the server? I would like to get hold of them as java.io.File instances. This has to be implemented in the backing bean, but I don't clearly understand how.
JSF won't save the file in any predefined location. It will basically just offer you the uploaded file in flavor of a javax.servlet.http.Part instance which is behind the scenes temporarily stored in server's memory and/or temporary disk storage location which you shouldn't worry about.
Important is that you need to read the Part as soon as possible when the bean action (listener) method is invoked. The temporary storage may be cleared out when the HTTP response associated with the HTTP request is completed. In other words, the uploaded file won't necessarily be available in a subsequent request.
So, given a
<h:form enctype="multipart/form-data">
<h:inputFile value="#{bean.uploadedFile}">
<f:ajax listener="#{bean.upload}" />
</h:inputFile>
</h:form>
You have basically 2 options to save it:
1. Read all raw file contents into a byte[]
You can use InputStream#readAllBytes() for this.
private Part uploadedFile; // +getter+setter
private String fileName;
private byte[] fileContents;
public void upload() {
fileName = Paths.get(uploadedFile.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
try (InputStream input = uploadedFile.getInputStream()) {
fileContents = input.readAllBytes();
}
catch (IOException e) {
// Show faces message?
}
}
Note the Path#getFileName(). This is a MSIE fix as to obtaining the submitted file name. This browser incorrectly sends the full file path along the name instead of only the file name.
In case you're not on Java 9 yet and therefore can't use InputStream#readAllBytes(), then head to Convert InputStream to byte array in Java for all other ways to convert InputStream to byte[].
Keep in mind that each byte of an uploaded file costs one byte of server memory. Be careful that your server don't exhaust of memory when users do this too often or can easily abuse your system in this way. If you want to avoid this, better use (temporary) files on local disk file system instead.
2. Or, write it to local disk file system
In order to save it to the desired location, you need to get the content by Part#getInputStream() and then copy it to the Path representing the location.
private Part uploadedFile; // +getter+setter
private File savedFile;
public void upload() {
String fileName = Paths.get(uploadedFile.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
savedFile = new File(uploads, fileName);
try (InputStream input = file.getInputStream()) {
Files.copy(input, savedFile.toPath());
}
catch (IOException e) {
// Show faces message?
}
}
Note the Path#getFileName(). This is a MSIE fix as to obtaining the submitted file name. This browser incorrectly sends the full file path along the name instead of only the file name.
The uploads folder and the filename is fully under your control. E.g. "/path/to/uploads" and Part#getSubmittedFileName() respectively. Keep in mind that any existing file would be overwritten, you might want to use File#createTempFile() to autogenerate a filename. You can find an elaborate example in this answer.
Do not use Part#write() as some prople may suggest. It will basically rename the file in the temporary storage location as identified by #MultipartConfig(location). Also do not use ExternalContext#getRealPath() in order to save the uploaded file in deploy folder. The file will get lost when the WAR is redeployed for the simple reason that the file is not contained in the original WAR. Always save it on an absolute path outside the deploy folder.
For a live demo of upload-and-preview feature, check the demo section of the <o:inputFile> page on OmniFaces showcase.
See also:
Write file into disk using JSF 2.2 inputFile
How to save uploaded file in JSF
Recommended way to save uploaded files in a servlet application

Link to download a zip file in JSF

I have a zip file in the server. I would like to download that file on click of a link.
Is there a way to create a link to download the zip file in JSF or PrimeFaces, like below HTML5 download attribute in client side?
<a href="/images/myw3schoolsimage.jpg" download>
The HTML5 download attribute has got nothing to do with it. It just allows you to specify an alternate filename which should appear in Save As dialog.
E.g.
<a href="foo.zip" download="bar.zip" />
will show the Save As dialog with bar.zip as filename, but actually provide content of foo.zip. Do note that the bar.zip doesn't necessarily need to exist in server.
As to your concrete problem, there are several ways of serving a file download in a JSF web application.
Just put that file in public web content folder.
WebContent
|-- META-INF
|-- WEB-INF
|-- files
| `-- foo.zip
|-- page.xhtml
:
Then you can refer it as:
download foo.zip
Or, if it's an external folder and you can't move it into public web content, then just tell the server to publish it. E.g. when you have all those files in /path/to/files path and you're using Tomcat server, then add the following into <Host> element of Tomcat's /conf/server.xml:
<Context docBase="/path/to/files" path="/files" />
Then you can refer it as:
download foo.zip
Or, if you have no control over server configuration somehow, or can't figure the server-specific way of publishing an arbitrary folder as a new web context, or it represents a temporary storage folder which you'd rather not publish into web, then create a web servlet which does the job. Leaving caching and resume outside consideration, it's as simple as:
#WebServlet("/files/*")
public class FileServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String filename = request.getPathInfo().substring(1);
File file = new File("/path/to/files", filename);
response.setHeader("Content-Type", getServletContext().getMimetype(filename));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
}
You can refer it the same way as #1:
download foo.zip
Though this is an old question, I would like to add this to #BalusC's answer for completeness (coudn't comment due to low reputation): The third solution by #BalusC ( with #WebServlet) can lead to 'Path Traversal Attack', if copy pasted as is.
You may try the attack(for Linux server) using URL:
<yourApplicationURLUntilContextPath>/files/%C0%AE/%C0%AE/%C0%AE/%C0%AE/%C0%AE/%C0%AE/%C0%AE/%C0%AE/%C0%AE/%C0%AE/etc/passwd
There are various solutions to this problem. One being, add the below check before copying the file to output stream:
if(!file.getAbsolutePath().equals(file.getCanonicalPath()))
{
response.sendError(404);
}
You may refer the link for more solutions to path traversal attack.
Hope it helps some developer...

Default config.xml?

On this page of the documentation, at the bottom, it says:
You can find full examples of Sphinx-4 configuration file in sources. For example, check the file
sphinx4/src/apps/edu/cmu/sphinx/demo/transcriber/config.xml
Well, I looked, and there is no config.xml in that directory, and there is no such file in any of the other folders inside of demo either.
So where can one find a default config file to use to get started with?
If I just do Configuration configuration = new Configuration();, would that be good enough to start with?
I recently found out that what you suggest is not enough. Take a look at the latest code on the Github repository. There is a default.config.xml file at https://github.com/cmusphinx/sphinx4/tree/master/sphinx4-core/src/main/resources/edu/cmu/sphinx/api, and the path to it is set in the Context class in package edu.cmu.sphinx.api:
public Context(Configuration config)
throws IOException, MalformedURLException
{
this("../sphinx4/sphinx4-core/src/main/resources/edu/cmu/sphinx/api/default.config.xml", config);
}

Using JDK's JAXB without ns2 prefix

After having read all posts about this on Oracle forums, Stackoverflow, java.net I'm finally posting here.
I'm using JAXB to create XML files but the problem is that it adds the famous ns2 prefix before my elements, I have tried all the solutions no one worked for me.
java -version gives "1.6.0_37"
Solution 1 : Using package-info.java
I created the file in my package containing my #Xml* annotated classes with the following content :
#XmlSchema(
namespace = "http://mynamespace",
elementFormDefault = XmlNsForm.QUALIFIED,
xmlns = {
#XmlNs(namespaceURI = "http://mynamespace", prefix = "")
}
)
package com.mypackage;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Solution 2 : NamespacePrefixMapper
I created the following class and set the mapper to the marshaller :
// Change mapper to avoid ns2 prefix on generated XML
class PreferredMapper extends NamespacePrefixMapper {
#Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
return "";
}
}
NamespacePrefixMapper mapper = new PreferredMapper();
try {
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper);
}
catch (PropertyException e) {
logger.info("No property for com.sun.xml.bind.namespacePrefixMapper found : " + e.getMessage());
}
With com.sun.xml.bind.namespacePrefixMapper nothing happens, with com.sun.xml.internal.bind.namespacePrefixMapper, it throws the exception.
I've also addded the maven dependency in my pom, but it seems that JRE version has a higher priority :
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.4</version>
</dependency>
Can you help me on this ?
PS : I can't include directly the jar in my classpath for build reasons.
PS2 : I can't use JDK7.
Thanks in advance.
Without the implementation of MOXy is not possible. JAXB if the preferred prefix is "", it generates a new one.
I had the same problem in the past, and I configured each prefix for each package-info.java.
NamespacePrefixMapper says in JAVADOC
null if there's no prefered prefix for the namespace URI.
In this case, the system will generate a prefix for you.
Otherwise the system will try to use the returned prefix,
but generally there's no guarantee if the prefix will be
actually used or not.
return "" to map this namespace URI to the default namespace.
Again, there's no guarantee that this preference will be
honored.
If this method returns "" when requirePrefix=true, the return
value will be ignored and the system will generate one"
else if use package-info
we know we can't bind to "", but we don't have any possible name at hand.
generate it here to avoid this namespace to be bound to "".
I hope I've given you all the answers about your question.
I had the same problem today. The production machine has Java 6 and when I deployed my application, I was getting the ns2 prefix. This is how I resolved it. Production server has only Java 1.6 patch 21
I made sure that I have a package-info.java file in my package where all the classes were generated using Jaxb. I checked it and the #XmlSchema was all auto generated, so I didn't mess with any of that. Don't use namespacemapper, that just confused me.
In my pom.xml file, I added jaxb-impl dependency:
com.sun.xml.bind
jaxb-impl
2.2.5-b04
and specified source and target as 1.6. Did a maven clean install and package and deployed into production, everything looks good.
Next step is to make sure that production machine is upgraded to Java 7. Hope this helps :)

Accessing properties file in a JSF application programmatically

I am trying to access the i18n properties file I'm using in my JSF application in code. (The idea is to have a page that displays its keys and values as a table actually.)
The project is a maven project, and in the src/resources/localization folder, and deployed in the war file in WEB-INF\classes\localization\
java.util.Properties prop = new java.util.Properties();
String path = "localization/stat_codes.properties";
InputStream foo = prop.getClass().getResourceAsStream(path);
But the variable foo turns out to be null whatever I set the path variable to, /WEB-INF/classes/localization/stat_codes.properties, "localization.stat_codes.properties" etc. A similar question is here, but there is no helpful answer there as well.
The Class#getResourceAsStream() can take a path which is relative to the location of the Class which you're using there as starting point. So, for example, if the class is located in the com.example package and you request the path foo/filename.properties, then it will actually load the com/example/foo/filename.properties file. But if you use /foo/filename.properties, then it will actually load foo/filename.properties from the classpath root.
So, your code
java.util.Properties prop = new java.util.Properties();
String path = "localization/stat_codes.properties";
InputStream foo = prop.getClass().getResourceAsStream(path);
will actually look for java/util/localization/stat_codes.properties file.
But in applications with a complex multiple classloader hierarchy, the one classloader isn't the other. The classloader which loaded the core Java classes does not necessarily have knowledge about files which are in the webapp's /WEB-INF/classes. So prefixing the path with / will not necessarily be the solution, it would still return null.
If you can guarantee that the current class is visible by the same classloader as the properties files (because they're in the same sub-root of the classpath, e.g. /WEB-INF/classes, then you should indeed use
String path = "/localization/stat_codes.properties";
InputStream foo = this.getClass().getResourceAsStream(path);
But if at some point, the properties files will be externalized because of more easy maintenance/editing during runtime so that you don't need to rebuild/redeploy/restart the webapp whenever you want to edit the files, then the above line of code will likely fail as well. The externalized location would be only accessible by a different classloader. The canonical solution is to use the thread's context classloader as starting point instead, it has access to all resources in the classpath.
String path = "localization/stat_codes.properties";
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream foo = loader.getResourceAsStream(path);
(note that this one cannot take a path starting with /, it's always relative to the common root)
See also:
Where to place and how to read configuration resource files in servlet based application?
ExternalContext#getResourceAsStream() returns null, where to place the resource file?
It seems that the culprit is the prop object, I supposed any object would work, but it has to be the current object (this) on which the method getClass() is invoked, it seems. Also, the path should start with a / since the localization directory resides in WEB-INF/classes.
String path = "localization/stat_codes.properties";
InputStream foo = this.getClass().getResourceAsStream(path);

Resources