Set path in web.xml relative to WEB-INF - path

I want to set a path in my web.xml which is relative to the WEB-INF or the WEB-INF/classes.
However, the following code (repository.home) seems to pick up a path relative to c: root drive path on my windows machine here.
<servlet>
<servlet-name>ContentRepository</servlet-name>
<servlet-class>org.apache.jackrabbit.servlet.jackrabbit.JackrabbitRepositoryServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>repository.home</param-name>
<param-value>/WEB-INF/classes/testit</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>JackrabbitServlet</servlet-name>
<servlet-class>com.orsa.seam.JackrabbitServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>

That parameter is OK, i.e. when you read it, it will be still a String with the value: /WEB-INF/classes/testit
A parameter in web.xml file is just a parameter - it's not a "path".
So the question is what you do with that parameter?
Since you are trying to access resources(files) inside a servlet container, you need to use specific methods, e.g. something like
ServletContext#getRealPath()
to get the real path of e.g. /WEB-INF/classes/testit, than
append to it what you need (thus having a full path to those files inside that directory), or subtract it from other "full paths", thus having the relative paths to it. E.g. if you have '/testit/test1.txt' '/testit/test2.txt' you can access those files by just appending them to the real path obtained above.
Or subtract that path from other 'full paths', thus having the relative path to your parameter. E.g. if you have the full path (c:/tomcat/webapps/myapp/WEB-INF/data/testit/test.txt), than you just need to subtract that full path of your parameter, so you will obtain the relative path: '/testit/test2.txt'

Related

Adding second UI to Vaadin 7 app causes problems

I have a Vaadin 7 application where I originally had just one UI. The following things happened, which I did not mind and even liked:
When installed new WAR file, all browser tabs currently opened to that URL gave the black "Connection failed" or "Session expired" error, forcing me to refresh. Also, I would often get a "server loading" error in the upper right corner while the application deployed. This one is kind of hard to explain, but hopefully this makes sense. None of this was triggered by my code directly, all of it was behavior I got from Vaadin out of the box.
If I was logged in to the same website (and same user) in multiple browser tabs, and then logged out of one tab, my code to logout/inactivate all tabs worked great - they all went back to the login screen, as I coded them to.
At that time, I had web.xml as follows:
web-app id="WebApp_ID" version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>vaadinwebsite</display-name>
<context-param>
<description>Vaadin production mode</description>
<param-name>productionMode</param-name>
<param-value>${productionMode}</param-value>
</context-param>
<servlet>
<!-- <servlet-name>WmsUIServlet</servlet-name> -->
<servlet-name>WmsServlet</servlet-name>
<servlet-class>com.mobiwms.website.WmsServlet</servlet-class>
<init-param>
<param-name>UI</param-name>
<param-value>com.mobiwms.website.WmsUI</param-value>
</init-param>
</servlet>
<servlet-mapping>
<!-- <servlet-name>WmsUIServlet</servlet-name> -->
<servlet-name>WmsServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- Uncomment if add more than one UI
<servlet-mapping>
<servlet-name>Vaadintutorial</servlet-name>
<url-pattern>/VAADIN/*</url-pattern>
</servlet-mapping>
-->
... <!-- some other stuff-->
</web-app>
I recently added a second UI, which meant I needed to tweak the path of the first UI. So I did the following:
Changed web.xml so it uses 3.0, and comment out servlet references in web.xml so it would use WebServlet annotations in the code.
Changed the url pattern of my first UI from #WebServlet(urlPatterns = "/*", name = "WmsServlet", asyncSupported = true) to #WebServlet(urlPatterns = {"/*", "/VAADIN/*"}, name = "WmsServlet", asyncSupported = true), as per the documentation. So this makes it so the "root" application is my main UI, like it was when I only had one UI. As per my web.xml snippet above, I always had a url pattern of "/*".
Added a new UI and url pattern using #WebServlet(urlPatterns = "/Registration/*", name = "WmsRegistrationServlet", asyncSupported = true).
Now I am getting the following weirdness:
Installing a new WAR does not force me to refresh. In other words, I don't even notice I need to refresh until I start doing something, at which point I get the normal black "communication failed", like normal.
When I am logged in on two tabs and logout, it definitely invalidates the session in the other tab (I see the black "communication failed" error), but it does not go back to the login screen like it used to.
At various times we see a failed to load widgetset error.
On occasion, when we are doing things, like uploading files, we get the black "communication failed" error.
The 2 UIs and servlets are much the same, just a different layout. The newer UI is a registration UI and so really only has one form, one view, and is very simple. The other is a full fledged application.
I tried it with asyncSupported = false on my newer application (the Registration UI), but that did not work. I then commented out #WebServlet(urlPatterns = "/Registration/*", name = "WmsRegistrationServlet", asyncSupported = false), so effectively my new UI is not accessible. This did not fix it either.
Since I also changed the web.xml such that I am using 3.0 (web.xml had 2.5 before this), I changed asyncSupport to false for both my UI servlets so it matches the default behavior for 2.5. This also did not fix it.
So then I commented out the Registration WebServlet annotation again and changed #WebServlet(urlPatterns = {"/*", "/VAADIN/*"}, name = "WmsServlet", asyncSupported = false) to #WebServlet(urlPatterns = "/*", name = "WmsServlet", asyncSupported = false) (so got rid of VAADIN reference). This actually fixed things, and now things work like before. So am I handling 2 UI's wrong? Maybe I am dealing with "/VAADIN/*" wrong?
Ok, after reading the documentation multiple times, I finally noticed one minor point they made:
You do not have to provide the above /VAADIN/* mapping if you serve
both the widget sets and (custom and default) themes statically in the
/VAADIN directory in the web application. The mapping simply allows
serving them dynamically from the Vaadin JAR. Serving them statically
is recommended for production environments as it is faster. If you
serve the content from within the same web application, you may not
have the root pattern /* for the Vaadin servlet, as then all the
requests would be mapped to the servlet.
So once I changed #WebServlet(urlPatterns = {"/*", "/VAADIN/*"}, name = "WmsServlet", asyncSupported = false) to #WebServlet(urlPatterns = "/*", name = "WmsServlet", asyncSupported = true), things worked much better. Since I am not using the VAADIN jar file, but the Vaadin stuff is in my WAR file that gets exploded to a directory (the default setup, as far as I know), it is effectively static, thus this works.
BTW, I set asyncSupported = true to get around the "A filter or servlet of the current chain does not support asynchronous operations." error (I mention this error here), although, honestly, I am not 100% sure I had to. Since it seems not to be hurting me, I left it as "true".

Unable to parse XML with multiple namespaces using tcl and tdom

I am trying to parse a XML using tcl and tdom package. I am having trouble doing this as the node I want to parse is a child to a node with multiple namespaces. How would I be able to parse the realmCode or title element? Below is what I have tried:
package require tdom
set XML {<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="http://www.cerner.com/cda_stylesheet/" ?>
<ClinicalDocument xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sdtc="urn:hl7-org:sdtc" xsi:schemaLocation="urn:hl7-org:v3 ../../../CDA%20R2/cda-schemas-and-samples/infrastructure/cda/CDA.xsd" classCode="DOCCLIN" moodCode="EVN">
<realmCode code="US" />
<title>Discharge Summary</title>
</ClinicalDocument>}
set nsmap {
a urn:hl7-org:v3
x http://www.w3.org/2001/XMLSchema-instance
s urn:hl7-org:sdtc
}
set doc [dom parse $XML]
set root [$doc documentElement]
set node [$root selectNodes -namespaces $nsmap "/a:ClinicalDocument/title"]
#set node [$root selectNodes "/ClinicalDocument/title"] ;# tried this as well - does not work
$doc delete
You need to specify the namespace for every level of the path, not just the root. Use
set title [$root selectNodes -namespaces $nsmap /a:ClinicalDocument/a:title]
set realm [$root selectNodes -namespaces $nsmap /a:ClinicalDocument/a:realmCode/#code]
etc.
This is more for the sake of completeness, and not necessarily recommended. You may instruct tDOM to simply ignore the namespaces. See -ignorexmlns.
Watch:
set doc [dom parse -ignorexmlns $XML]
set root [$doc documentElement]
$root selectNodes "/ClinicalDocument/title"
$root selectNodes "/ClinicalDocument/realmCode/#code"
The consequences are obvious: ambiguity.

Access to a directory that contains special characters in JBoss

I cannot access a directory that contains special characters in JBoss. I have configured JBoss so the directory listing is enabled.
For example, let's say I have a war (myApp.war) deployed in JBoss that contains a directory named "Categoría 1".
In order to access the war contents from a browser, I browse correctly to:
"http://localhost:8080/myApp/"
When I browse this URL, I get the contents displayed correctly, including "Categoría 1" directory name. The URL that the browser displays as the link to get this directory is:
"http://localhost:8080/myApp/Categor%C3%ADa%201/"
But When I try to browse this directory, I get a 404 error:
"JBWEB000065: HTTP Status 404 - /myApp/Categor%C3%ADa%201/
JBWEB000309: type JBWEB000067: Status report
JBWEB000068: message /myApp/Categor%C3%ADa%201/
JBWEB000069: description JBWEB000124: The requested resource is not available.
JBoss Web/7.2.2.Final-redhat-1"
My final intention is to get the directory contents from a servlet and parse the response to display these contents in a different way, not just the html returned as the result of browsing the directory. But since I was having the same problem with character encoding, I just tested something simpler, with a Chrome or iExplorer browser, but the problem seems to be the same.
I have found how to solve this. It is related to the JBoss configuration. The encoding must be set to UTF-8 (in my case). The configuration file for standalone server is located in:
JBoss_base_directory/standalone/configuration/standalone.xml
and the properties to set:
<system-properties>
<property name="org.apache.catalina.connector.URI_ENCODING" value="UTF-8"/>
<property name="org.apache.catalina.connector.USE_BODY_ENCODING_FOR_QUERY_STRING" value="true"/>
</system-properties>

Reading properties file in JSF2.0 which can work in war also

To read a properties file in JSF2.0 with Glassfishv3 webserver, which is located at root directory of my web application, I am using below code-
ServletContext ctx = (ServletContext) FacesContext
.getCurrentInstance().getExternalContext().getContext();
String deploymentDirectoryPath = ctx.getRealPath("/");
Properties prop = new Properties();
prop.load(new FileInputStream(deploymentDirectoryPath
+ File.separator + "portal-config.properties"));
Below is the screenshot of web portal-
While running the portal I am getting FileNotFound Error, since the file is not present in glassfish domain.
Is there any way to read properties file which can work in both the situations, at development stage and in war file also?
You should never use java.io.File to refer web resources. It knows nothing about the context it is sitting in. You should also never use ServletContext#getRealPath() as it may return null when the server is configured to expand WAR file in memory instead of on disk, which is beyond your control in 3rd party hosts.
Just use ExternalContext#getResourceAsStream() to get the web resource directly in flavor of an InputStream. It takes a path relative to the webcontent root.
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
properties.load(ec.getResourceAsStream("/portal-config.properties"));
See also:
getResourceAsStream() vs FileInputStream
What does servletcontext.getRealPath("/") mean and when should I use it
Where to place and how to read configuration resource files in servlet based application?
Update it does not seem to be a web resource at all. You should move the file into the "WebContent" folder as shown in the screenshot. Or, better, the /WEB-INF folder so that nobody can access it by URL.
properties.load(ec.getResourceAsStream("/WEB-INF/portal-config.properties"));
An alternative would be to put it in the classpath, the "Java source" folder as shown in the screenshot. You don't need to put it in a package, that's optional. Assuming that you didn't put it in a package, then do so:
ClassLoader cl = Thread.currentThread().getContextClassLoader();
properties.load(cl.getResourceAsStream("portal-config.properties"));
(note that the path may not start with a slash!)

Enable Tiles devMode like Struts' devMode to reload tiles.xml with each request

Does Apache Tiles have a devMove like Struts that would reload the tiles.xml file with each request? If so, how can this be enabled?
Here is another working configuration that uses Listener instead of Filter.
(since Tiles 2.1.2)
In web.xml:
<context-param>
<param-name>org.apache.tiles.definition.dao.LocaleUrlDefinitionDAO.CHECK_REFRESH</param-name>
<param-value>true</param-value>
</context-param>
<listener>
<listener-class>org.apache.tiles.web.startup.TilesListener</listener-class>
</listener>
I've used tiles, but have never tried to dynamically reload it.
However, this page : http://tiles.apache.org/tutorial/configuration.html
says:
Load the Tiles filter. It is useful if your definition files can be changed and you periodically need to reload them.
The following has worked for me using tiles 2.2.2 inside servlet container.
....
import org.apache.tiles.definition.DefinitionsFactory;
import org.apache.tiles.definition.UnresolvingLocaleDefinitionsFactory;
import org.apache.tiles.definition.dao.ResolvingLocaleUrlDefinitionDAO;
import org.apache.tiles.impl.BasicTilesContainer;
import org.apache.tiles.servlet.context.ServletUtil;
//When using SimpleTilesListener => BasicTilesContainer is returned
//When using StrutsTilesListener => CachingTilesContainer is returned which extends BasicTilesContainer
BasicTilesContainer tilesCont = (BasicTilesContainer) ServletUtil.getContainer(ServletActionContext.getServletContext());
DefinitionsFactory defFact = tilesCont.getDefinitionsFactory();
Field field= UnresolvingLocaleDefinitionsFactory.class.getDeclaredField("definitionDao");
field.setAccessible(true);
ResolvingLocaleUrlDefinitionDAO rludDAO = (ResolvingLocaleUrlDefinitionDAO)field.get(defFact);
rludDAO.refresh();

Resources