How to serve static web pages from a JSF application using Glassfish - jsf

I have a JSF 2.0 application running under Glassfish 3.1.1 and I need to serve static web pages that are physically located apart from my application root that is created when my WAR file is deployed. I've found various references (like this one and this one) to defining an alternate docroot using a tag such as
<property name="alternatedocroot_1" value="from=/myimages/* dir=/images"/>
added to sun-web.xml (which I would presume means glassfish-web.xml in Glassfish 3.1.1). I can't seem to get it to work, however. In my case, I think the problem is that glassfish-web.xml simply isn't defining enough context for the alternate docroot to have any meaning:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
<class-loader delegate="true"/>
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class' java code.</description>
</property>
</jsp-config>
<property name="alternatedocroot_1" value="from=/myimages/* dir=/images"/>
</glassfish-web-app>
The meat of my application definition seems to be much more in web.xml than glassfish-web.xml. Do I perhaps need to put something there instead to reference the alternate docroot?

This exact configuration requires a /images/myimages folder relative to the absolute root of the same disk as where the JVM of the webserver is running in. A file foo.png in that folder is then available by http://localhost:8080/contextname/myimages/foo.png.
A common confusion around this setting is that the from attribute is been interpreted as alone the context path in URL and not as an actual subfolder in the dir location. But this is thus not true.
If you're running Glassfish on a Windows environment then you need to specify the disk letter in the dir as well like so dir=C:/images.

Related

OmniFaces CDNResourceHandler could not find resources when not included locally

I'm using OmniFaces CDNResourceHandler to point my resources to a CDN, instead of local files.
I added this line in my XHTML file: <h:outputStylesheet library="twitter-bootstrap" name="bootstrap.min.css" />
And my faces-config.xml have this line:
<context-param>
<param-name>org.omnifaces.CDN_RESOURCE_HANDLER_URLS</param-name>
<param-value>
twitter-bootstrap:bootstrap.min.css=https://somehost/twitter-bootstrap/3.3.7/bootstrap.min.css
</param-value>
</context-param>
And I'm getting this error when access the page:
Unable to find resource twitter-bootstrap, bootstrap.min.css
Note: When I access the file at https://somehost/twitter-bootstrap/bootstrap.min.css I can download the file properly.
I'm using Mojarra under Wildfly configured to Development stage.
The resource handler is properly configured at faces-config.xml file.
<application>
<resource-handler>org.omnifaces.resourcehandler.CDNResourceHandler</resource-handler>
</application>
I did some tests, and I notice that the error doesn't occurs if I create an empty file bootstrap.min.css under WEBAPP_FOLDER/resources/twitter-bootstrap. If I delete the file, the errors occurs again.
Even I use CDN, do I need to keep resources locally?
The CDNResourceHandler is primarily intented to move auto-included JSF resources to a CDN, such as jsf.js file from <f:ajax>, or primefaces.js and jquery.js from PrimeFaces, or to automatically switch to a CDN when installed in production.
You don't need it in your case with a permanent CDN resource. Just use plain <link>.
<link rel="stylesheet" src="https://somehost/twitter-bootstrap/bootstrap.min.css" />
This is also explicitly mentioned in the CDNResourceHandler documentation.
For non-JSF resources, you can just keep using plain HTML <script> and <link> elements referring the external URL
Update: as you're not the first one who wondered about this, I've as per issue 122 bypassed this technical restriction for OmniFaces 2.6. In other words, you do not necessarily need a local resource anymore.

EJBAccessException when invoke local EJB on Wildfly

When I try to invoke local EJB I get EJBAccessException running my migrated Glassfish web application on Wildfly 8.2. I found the JBoss documentation all other than strait forward and need help, i.e. no link to JBoss documentation please.
I have no #DeclareRoles notation on my EJB to make it simple for now. I tried with and without using the security realm other adding jboss-web and jboss-ejb3 to tie the bean to a realm. But I still get the same exception.
I've read these tutorials, but can't get it to work. I am using MongoDB and JDBC security realm setup don't help me much. But for now I bypass the user-role authentication.
Migrating a Java EE App from GlassFish to WildFly
Invoke EJB from WildFly safely
And others
How can I run local EJB on Wildfly in my web application?
#Stateless
public class MyBean {
public String sayHello() {
...
jboss-web.xml
<jboss-web>
<security-domain>other</security-domain>
</jboss-web>
jboss-ejb3.xml
<assembly-descriptor>
<s:security>
<!-- Even wildcard * is supported -->
<ejb-name>*</ejb-name>
<!-- Name of the security domain which is configured in the EJB3 subsystem -->
<s:security-domain>other</s:security-domain>
</s:security>
</assembly-descriptor>
In WildFly 8, such methods which have no explicit security configurations, in a secured bean, will be treated similar to a method with #DenyAll configuration.
This behaviour can be controlled via the jboss-ejb3.xml deployment descriptor at a per bean level or a per deployment level as follows:
<?xml version="1.0" encoding="UTF-8"?>
<jboss:jboss
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:s="urn:security:1.1"
version="3.1" impl-version="2.0">
<assembly-descriptor>
<s:security>
<!-- Even wildcard * is supported where * is equivalent to all EJBs in the deployment -->
<ejb-name>FooBean</ejb-name>
<s:missing-method-permissions-deny-access>false</s:missing-method-permissions-deny-access>
</s:security>
</assembly-descriptor>
</jboss:jboss>
Setting missing-method-permissions-deny-access to false allows access to such methods for all users i.e. the behaviour will be switched to be similar to #PermitAll.

Inject jndi string resource on embedded glassfish using CDI not working

So I created a custom reference in the domain.xml
<custom-resource res-type="java.lang.String" jndi-name="jndi/myResource" factory-class="org.glassfish.resources.custom.factory.PrimitivesAndStringFactory">
<property name="value" value="myValue"/>
</custom-resource>
And referencing it through #Resource(lookup = "jndi/myResource") in a #ApplicationScoped bean.
I am also starting the server with the endorsed directory(containing the endorsed-api.jar). Still when I reference the resource, its not injecting and throwing a null.
Looks like everything is setup correctly, not sure what I am missing here.
And yes, I have beans.xml in the Meta-inf directory too.

Externalizing Tomcat webapp config from .war file

I am having trouble with configuring a webapp in Tomcat 7. In my WAR file, there is a properties file myApp/WEB-INF/classes/myProps.props, and it contains environment-specific properites. I am trying to override that configuration file on the server, so that the same WAR file will deploy to multiple environments.
I heard there was a way to do this using replacement config files in tomcat/conf/Catalina/myApp. This is the method I am having trouble figuring out.
Also, myApp.war is one of many running on the same Tomcat server, and it does not run as localhost. I want to be able to solve this problem for several of the webapps.
Server version: Apache Tomcat/7.0.23
Server built: Nov 20 2011 07:36:25
Server number: 7.0.23.0
OS Name: Linux
Your tomcat/conf/Catalina/<host> can contain context descriptors that let you configure lots of things including defining "environment entries", which are accessible from Java via JNDI. There are lots of ways to go about using it. Personally, I set an environment entry which is the file system path to my properties file. My app is built to check for this entry, and if it doesn't exist, look for the file on the classpath instead. That way, in dev, we have the dev properties right there on the classpath, but when we build and deploy, we point it to an external file.
There's good documentation for configuring a context on the Tomcat website. See the Defining a Context section on details of how to create the file and where to put it.
As an example, if your host is named myHost and your app is a war file named myApp.war in the webapps directory, then you could create tomcat/conf/Catalina/myHost/myApp.xml with this content:
<Context>
<Environment name="configurationPath" value="/home/tomcat/myApp.properties" type="java.lang.String"/>
</Context>
Then from your code, you'd do a JNDI lookup on java:comp/env/configurationPath (95% certainty here) to get that string value.
I like .properties files instead of
JNDI - why build complex object during program configuration instead of initialization time?
system properties - you can't separately configure several instances of same WAR in single Tomcat
context parameters - they accessible only in javax.servlet.Filter, javax.servlet.ServletContextListener which my be inconvenient
Tomcat 7 Context hold Loader element. According to docs deployment descriptor (what in <Context> tag) can be placed in:
$CATALINA_BASE/conf/server.xml - bad - require server restarts in order to reread config
$CATALINA_BASE/conf/context.xml - bad - shared across all applications
$CATALINA_BASE/work/$APP.war:/META-INF/context.xml - bad - require repackaging in order to change config
$CATALINA_BASE/work/[enginename]/[hostname]/$APP/META-INF/context.xml - nice, but see last option!!
$CATALINA_BASE/webapps/$APP/META-INF/context.xml - nice, but see last option!!
$CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml - best - completely out of application and automatically scanned for changes!!!
Context can hold custom Loader org.apache.catalina.loader.VirtualWebappLoader (available in modern Tomcat 7, you can add own separate classpath to your .properties), and Parameter (accessed via FilterConfig.getServletContext().getInitParameter(name)) and Environment (accessed via new InitialContext().lookup("java:comp/env").lookup("name")):
<Context docBase="${basedir}/src/main/webapp"
reloadable="true">
<!-- http://tomcat.apache.org/tomcat-7.0-doc/config/context.html -->
<Resources className="org.apache.naming.resources.VirtualDirContext"
extraResourcePaths="/WEB-INF/classes=${basedir}/target/classes,/WEB-INF/lib=${basedir}/target/${project.build.finalName}/WEB-INF/lib"/>
<Loader className="org.apache.catalina.loader.VirtualWebappLoader"
virtualClasspath="${basedir}/target/classes;${basedir}/target/${project.build.finalName}/WEB-INF/lib"/>
<JarScanner scanAllDirectories="true"/>
<Parameter name="min" value="dev"/>
<Environment name="app.devel.ldap" value="USER" type="java.lang.String" override="true"/>
<Environment name="app.devel.permitAll" value="true" type="java.lang.String" override="true"/>
</Context>
If you use Spring and it's XML config:
<context:property-placeholder location="classpath:app.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#${db.host}:${db.port}:${db.user}"/>
<property name="username" value="${db.user}"/>
<property name="password" value="${db.pass}"/>
</bean>
With Spring injecting above properties into bean fields are easy:
#Value("${db.user}") String defaultSchema;
instead of JNDI:
#Inject ApplicationContext context;
Enviroment env = context.getEnvironment();
String defaultSchema = env.getProperty("db.user");
Note also that EL allow this (default values and deep recursive substitution):
#Value('${db.user:testdb}') private String dbUserName;
<property name='username' value='${db.user.${env}}'/>
See also:
Adding a directory to tomcat classpath
Can I create a custom classpath on a per application basis in Tomcat
How to read a properties file outside my webapp context in Tomcat
Configure Tomcat to use properties file to load DB connection information
Should you set up database connection properties in server.xml or context.xml
Externalize Tomcat configuration
NOTE With extending classpath to live directory you also allowed to externilize any other configs, like logging, auth, atc. I externilize logback.xmlin such way.
UPDATE Tomcat 8 change syntax for <Resources> and <Loader> elements, corresponding part now look like:
<Resources>
<PostResources className="org.apache.catalina.webresources.DirResourceSet"
webAppMount="/WEB-INF/classes" base="${basedir}/target/classes" />
<PostResources className="org.apache.catalina.webresources.DirResourceSet"
webAppMount="/WEB-INF/lib" base="${basedir}/target/${project.build.finalName}/WEB-INF/lib" />
</Resources>
You can try to place your configuration (properties file) in Apache Tomcat\lib in JAR file and remove it from the web application. When the Tomcat's class loader won't find your config in webapp it will try to find in "lib" directory. So you can externalize your configuration just moving the config to global lib dir (it's shared among other webapps).
I just added a setenv.bat or setenv.sh script in the bin folder of tomcat. Set the classpath variable like
set CLASSPATH=my-propery-folder

does JWS support to launch One-Jar

Can I supposed to launch One-Jar using JWS? One-JAR provides custom classloader that knows how to load classes and resources from a jars inside an archive whereas in JWS we need to specify each JAR that is being used in resources.
What I supposed to specify in JNLP if I am trying to launch One-Jar -
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="" href="">
<information>
<title>Application</title>
<vendor>ABC</vendor>
</information>
<resources>
<!-- Application Resources -->
<j2se version="1.5+"
href="http://java.sun.com/products/autodl/j2se"/>
<jar href="Application.jar" main="true" download="eager" />
</resources>
<application-desc main-class="com.simontuffs.onejar.Boot">
</application-desc>
<update check="background"/>
<security>
<all-permissions/>
</security>
</jnlp>
My Application JAR that is One-JAR contains -
com\simontuffs\onejar\<contains complied classes> like JarClassLoader$1.class etc
lib/<contains all jar>
OneJar.class
main/<my application's jar>
META-INF\MANIFEST.MF\ <contains >
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.1
Created-By: One-Jar 0.96 Ant taskdef
Main-Class: com.simontuffs.onejar.Boot
One-Jar-Main-Class: com.application.main.Entry
Name: com/simontuffs/onejar/Boot$3.class
SHA1-Digest: +LPrezs+UEFcE3J7QvumcAEO8Z0=
Name: OneJar.class
SHA1-Digest: 28pzzJWqEpLk1xFwJ/jsAav8LyI=
Name: lib/commons-io-1.4.jar
SHA1-Digest: qHYtB+ds/eI5Ulel2ke6fB29Pc4=
etc..etc..
How to specify these com/simontuffs/onejar/Boot$3.class paths in resource ?
Part of the problem of supporting tools like One-Jar is that loading Jars within Jars requires a custom class-loader. By default JWS will use the usual JRE class-loaders - which do not support it.
There are two possible ways that you might get around that (that I know of).
1. Get access to the custom class-loader.
Get an instance of the custom loader used by One-Jar and set it as the context class-loader. This would require a trusted app., but I get the impression that your app. is trusted.
I have no idea if the One-Jar API provides this loader for your own app.'s use.
2. Use some options when building.
From Options and VM Properties..
one-jar.jar.names
true: Recorded classes are kept in directories corresponding to their jar names.
false: Recorded classes are flattened into a single directory.
Duplicates are ignored (first wins)
The 2nd option sounds like a standard 'fat jar'. That should work with the conventional (default) class-loader used by JWS.

Resources