Jetty Classloading issue - java

I'm using the jetty maven plugin to run a webapp locally and I'm getting a class cast exception when I try to pull in a JNDI resource.
I have a jetty config with a resource object, which is a configuration bean that is utilized via JNDI. This class resides in a different jar on the classpath that is in the lib directory:
<Configure class="org.mortbay.jetty.Server">
<New class="org.mortbay.jetty.plus.naming.Resource">
<Arg>config/MyConfigObject</Arg>
<Arg>
<New class="my.config.ConfigObject">
<Set name="foo">bar</Set>
</New>
</Arg>
</New>
</Configure>
This is retrieved via Spring:
<bean id="MyConfigObject" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/config/MyConfigObject" />
</bean>
Inside of a servlet, I'm grabbing the object manually:
final MyConfigObject config = (MyConfigObject) applicationContext.getBean("MyConfigObject");
But when I try to access the servlet, I get:
java.lang.ClassCastException: my.config.MyConfigObject cannot be cast to my.config.MyConfigObject
I'm pretty sure the problem is due to class loading, but I'm not 100% certain. MyConfigObject's class loader is the default sun class loader, while the thread's current class loader is jetty's WebAppClassLoader. My jar is in WEB-INF/lib, and I've even added it manually to extraClasspath in the maven plugin configuration:
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.25</version>
<configuration>
<jettyConfig>${basedir}/test/jetty.xml</jettyConfig>
<webAppSourceDirectory>${basedir}/target/${project.artifactId}</webAppSourceDirectory>
<webXml>${basedir}/war/WEB-INF/web.xml</webXml>
<webAppConfig>
<extraClasspath>${basedir}/target/${project.artifactId}/WEB-INF/lib/myConfigJar-1.0.jar</extraClasspath>
</webAppConfig>
</configuration>
<dependencies>
<dependency>
<groupId>testing</groupId>
<artifactId>myConfigJar</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</plugin>
I'm kind of stuck at this point. Does anyone know how to resolve this?

The problem is that you've got the jar listed in too many places - you attempts to add it to extraClasspath will actually make it worse, not better.
You say it's in WEB-INF/lib, but I assume it's also listed as a dependency in your pom.xml
You don't want to do that, you need to have 1 single reference to it. Either as a dependency in your pom.xml or in your lib directory, or in extraClasspath, but only in 1 place.
(Hint: pom.xml is almost certainly the right place, get rid of the others)

your webapp should not include the "my.config.MyConfigObject" class (and related classes) in it.
the underlying problem is that you are getting the class loaded by 2 different classloaders. you need to eliminate the class from your webapp classloader so that your webapp will use the same class that jetty is using.

Related

Eclipselink static weaving in Java web application - Eclipse

Im currently working on project where I develop Java web application. I use IDE Eclipse.
As data layer I use EclipseLink(2.6) JPA. Web application runs on Tomcat webserver(7). Now I realized that I need to use LAZY fetching for my Entities because of performance issues.
After some research I figured out that I need to use "static weaving", acording to manual pages, I found that I have 3 possibilities how to do that: Ant, Maven or use command line.
Since I have no experience with Ant, Maven or command line options I dont know how to continue now. I would like to pick easiest solution, which is Ant (from my begginer point of view). Can you suggest?
My project is divided into two projects:
JPA project, with persistence entities and database operations
Java application with servlets and JSP, this project contains link to JPA project
I run that application on:
remote Tomcat server - then I generate .war file that contains both projects and then I upload it on server
localhost - then I run that application directly from Eclipse (Run As -> localhost)
Can please somebody tell me process how I should continue now?
Shall I specify two steps Ant build that firstly create .jar from my JPA project, then do static weaving and continue in building web project to .war? So far I found only Ant builds where .jar applications are generated, not sure how it differ to web applications. Any tutorials there?
Can please somebody share some hits? I am complete beginer in this area - perhaps I missed some easy ways. My main goal is to have .war file that contains entities with static weaving, secondary goal is to automate deploying on tomcat localhost server, as I do it now from Eclipse IDE.
Thank you.
I can only speak for the Maven side of things, because thats the one I have experience with.
Inside your pom.xml , under plugins you will have to add the maven staticweave plugin:
<plugin>
<groupId>de.empulse.eclipselink</groupId>
<artifactId>staticweave-maven-plugin</artifactId>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>weave</goal>
</goals>
<configuration>
<persistenceXMLLocation>META-INF/persistence.xml</persistenceXMLLocation>>
</configuration>
</execution>
</executions>
</plugin>
You may have to adjust your persistence.xml-location.
Inside your persistence.xml you will need to activate static weaving:
<properties>
<property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.H2Platform" />
<property name="eclipselink.weaving" value = "static"/>
<property name="eclipselink.weaving.internal" value="true"/>
<property name="eclipselink.weaving.lazy" value="true" />
<property name="eclipselink.weaving.changetracking" value="true" />
<property name="eclipselink.weaving.fetchgroups" value="true" />
<property name="eclipselink.weaving.eager" value="false" />
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />
<property name="eclipselink.logging.level" value="FINEST" />
</properties>
Again, you may have to change your platform, desired logging level and the other parameters.
If you leave all the eclipselink.weaving.*-parameters out, they will have their default values.
The static weaving happens in the process-classes phase of the maven lifecycle after the compile phase. If you have packaging set to war, you will get a single *.war-file that you can then deploy.
If you would really rather do it via ant-task, you should look at
https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Performance/Weaving/Static_Weaving#Use_the_weave_Ant_Task
I can't really answer any questions about that though.

merge properties files of two modules in spring

I have a Maven project with multiple modules. Module ModuleB uses ModuleA as an internal Maven dependency. In moduleA I have a Spring xml config module.a.xml that loads a module.a.properties file. In the Spring xml config of moduleB I import the module.b.properties file together with the module.a.xml config.
In the end I end up with a Spring xml config with two property file imports. Depending of the order of the imports I can only access properties of one file: either module.a.properties or module.b.properties. How can I use both properties at the same time?
The problem with a solution using the PropertyPlaceholderConfigurer is that the properties files reside at different modules and moduleB shouldn't worry about a properties file of moduleA.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" id="corePlaceHolder">
<property name="locations">
<list>
<value>classpath:modula.a.properties</value>
<value>classpath:modula.b.properties</value>
</list>
</property>
</bean>
The problem with using ignore-unresolvable="true" is that a forgotten property can easily be missed and putting ignore-unresolvable="true" on the property-placeholder can easily be missed.
<context:property-placeholder location="module.a.properties" order="0" ignore-unresolvable="true"/>
<context:property-placeholder location="module.b.properties" order="1" ignore-unresolvable="true"/>
Not sure this can solve your problem but, since you are using a maven multi-module build, have you considered suing a maven plugin to create a third properties file as a merge of A and B with proper override strategy?
Here is a sample using maven-merge-properties-plugin
<plugin>
<groupId>org.beardedgeeks</groupId>
<artifactId>maven-merge-properties-plugin</artifactId>
<version>0.2</version>
<configuration>
<merges>
<merge>
<targetFile>${moduleB.output.dir}/module-final.properties</targetFile>
<propertiesFiles>
<propertiesFile>${moduleB.src.dir}/moduleB.properties</propertiesFile>
<propertiesFile>${moduleA.src.dir}/moduleA.properties</propertiesFile>
</propertiesFiles>
</merge>
</merges>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>merge</goal>
</goals>
</execution>
</executions>
</plugin>
In this way you will get all A and B properties in just on file. If a property exists on both A and B, B will win (check file order in configuration).
Being both modules in the same project retrieve both files should be quite easy.
You could even use another plugin to unpack just needed properties files from external jars.
Hope this helps.

Java SQL DataSource Resource Configuration

In Java Spring, I am trying to keep my database settings outside of the main app so that it can be configured on other servers with minimal effort. I am using Tomcat 7 for my production server and a Jetty server (jetty-maven-plugin version 8.1.14.v20131031) for development.
The main problem I am running into is I cannot get the working Tomcat 7 configuration to translate to Jetty using the same class (javax.sql.DataSource). I am starting with this class, opposed to a more robust one so that I am starting with something as basic as possible.
If this is a case where there is no direct translation between the two servers, or this is simply bad practice I am looking for what would be a good practice or standard.
For example, this answer is an alternative configuration that uses a different class, and works with Jetty. (However it doesn't answer why the basic DataSource class works with Tomcat and not with Jetty.)
I have the a Resource entry in server.xml like so:
<Context path="/" docBase="/var/lib/tomcat7/webapps/myapp" reloadable="true">
<Resource name="mysql-dataSource" auth="Container" type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/dbname"
username="dbuser"
password="dbuser" />
</Context>
jetty-maven-plugin POM entry:
...
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.14.v20131031</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.29</version>
</dependency>
</dependencies>
<configuration>
<!-- <useProvidedScope>?</useProvidedScope> -->
<webApp>
<jettyEnvXml>${basedir}/jetty-env.xml</jettyEnvXml>
</webApp>
</configuration>
</plugin>
...
This works fine in Tomcat7.
For Jetty, I am using jetty-env.xml with the following configuration:
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.eclipse.org/configure.dtd">
<Configure id="Server" class="org.eclipse.jetty.webapp.WebAppContext">
<New id="ds" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg>mysql-dataSource</Arg>
<Arg>
<New class="javax.sql.DataSource">
<Set name="driverClassName">com.mysql.jdbc.Driver</Set>
<Set name="url">jdbc:mysql://localhost:3306/dbname</Set>
<Set name="username">dbuser</Set>
<Set name="password">dbuser</Set>
</New>
</Arg>
</New>
</Configure>
With that I get this error:
java.lang.IllegalStateException: No Constructor: <New class="javax.sql.DataSource">...
Add this
<Arg></Arg>
above
<Arg>mysql-dataSource</Arg>
As first "Arg" is the scope, and without it, the rest of your arguments are out of position, and are probably causing your issue.
For more information Jetty/Howto/Configure JNDI Datasource
Edit :
Have you add scope provided for the specific version of Jetty ?

How to use JASPI/JASPIC on Jetty?

On Jetty's main project page compatibility with JASPI (JASPIC/JSR 196) is mentioned.
However, the distribution of Jetty 8 does not seem to contain any classes related to JASPI. There's a jetty-security-8.1.8.v20121106.jar jar in [jetty home]/lib, but this one does not contain any of the JASPIC/JASPI types.
The documentation about JASPIC/JASPI on the Jetty wiki is only a placeholder and does not contain any information.
After some Googling I found JavaDocs on the Eclipse site and discovered there should be a jetty-jaspi-8.1.8.v20121106.jar somewhere. Those JavaDocs are included in the distribution as well. Finally, a jetty-jaspi repo appears at Github.
Obviously there is some amount of support available, but why are those classes seemingly not present in the Jetty distribution and where is the documentation on how to configure this? What am I missing?
This project (https://github.com/guofengzh/jaspi-on-jetty) is a working example of the JASPI API in jetty that uses geronimo-jaspi which in turn calls back to the jetty-jaspi modules for the authentication. Geronimo seems to be providing the configuration mechanism and jetty the authentication modules themselves in this example.
It seems as though you can select a form, digest or basic authentication methods. A quick test of the form based login has shown it appears to function.
The Jaspi authentication factory is setup in jetty-web.xml like so:
<Set name="securityHandler">
<New class="org.eclipse.jetty.security.ConstraintSecurityHandler">
<Set name="loginService">
<New class="org.eclipse.jetty.plus.jaas.JAASLoginService">
<Set name="name">JAASRealm</Set>
<Set name="loginModuleName">jaas</Set>
</New>
</Set>
<Set name="authenticatorFactory">
<New class="org.eclipse.jetty.security.jaspi.JaspiAuthenticatorFactory" />
</Set>
</New>
</Set>
And the jaspi configuration file is referenced via a system property in the pom.xml file:
<systemProperty>
<name>org.apache.geronimo.jaspic.configurationFile</name>
<value>./conf/jaspi/form-test-jaspi-2.xml</value>
</systemProperty>
Additionally, the jaspi library you mentioned is added as a dependency in the pom, along with the geronimo jaspi implementation:
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jaspi</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.components</groupId>
<artifactId>geronimo-jaspi</artifactId>
<version>2.0.0</version>
</dependency>
I have also been unable to find documenation on the topic. It seems as though the jetty-jaspi module is not one of the standard start options, but could be added to the ${jetty.home/lib/ext} directory (see Jetty classloading).

How to instruct Maven to ignore my main/resources/persistence.xml in favor of test/...?

I have two persistence.xml files, for the sake of testing:
src/main/resources/META-INF/persistence.xml
src/test/resources/META-INF/persistence.xml
How to instruct Maven to ignore the first file during testing? Now it is not ignored since OpenEJB says:
ERROR - FAIL ... Finder: #PersistenceContext unitName has multiple matches:
unitName "abc" has 2 possible matches.
Check out the alternate descriptors functionality which is aimed at what you're trying to do.
Try this setup:
src/main/resources/META-INF/persistence.xml
src/main/resources/META-INF/test.persistence.xml
Then you can construct OpenEJB to prefer the test.persistence.xml file by setting the openejb.altdd.prefix System or InitialContext property to test
A different possible solution could be to override the persistence unit properties in the test. With that approach you could avoid the need for a second persistence.xml which can be nice as maintaining two can be a pain.
You can use the Maven approach, but be aware that per spec the persistence provider will only look (aka scan) for #Entity beans in the exact jar or directory where the persistence.xml is found. So be keenly aware that in Maven these are two different locations:
target/classes
target/test-classes
EDIT More details on the overriding capabilities
You can override any property in your test setup via either system properties or the initial context properties (this includes jndi.properties files). The format is:
<unit-name>.<property>=<value>
So for example with the following persistence.xml:
<persistence>
<persistence-unit name="movie-unit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>movieDatabase</jta-data-source>
<non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.max_fetch_depth" value="3"/>
</properties>
</persistence-unit>
</persistence>
You can override and add persistence unit properties in your test case. There are currently no facilities for removing them (if you have a need for that let us know – it hasn't really come up so far).
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY,"org.apache.openejb.client.LocalInitialContextFactory");
p.put("movie-unit.hibernate.hbm2ddl.auto", "update");
p.put("movie-unit.hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
context = new InitialContext(p);
Or alternatively via a jndi.properties file
java.naming.factory.initial=org.apache.openejb.client.LocalInitialContextFactory
movie-unit.hibernate.hbm2ddl.auto = update
movie-unit.hibernate.dialect = org.hibernate.dialect.HSQLDialect
I think you can create two profiles in your pom.xml:
<properties>
<environment>dev</environment>
</properties>
<profiles>
<profile>
<id>prod</id>
<properties>
<environment>test</environment>
</properties>
</profile>
</profiles>
After that, in your src folder, create two folders named dev/resoruces and test/resources and copy your different resources there. After that, add something like this:
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>false</filtering>
</resource>
<resource>
<directory>${basedir}/src/main/${environment}/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
The ${basedir} depends on the command line parameter, it can be test or dev.
You run the maven command like this: mvn clean package -P test.
I have been testing these and other similar solutions without involving the pom.xml... In my opinion, the best way to solve this issue is to have two application-context.xml (one only to be used in test classes) and to add a custom persistence unit manager bean in the test's application-context.xml. Like this example:
<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocation">
<value>classpath*:META-INF/test.persistence.xml</value>
</property>
<property name="defaultDataSource" ref="dataSource"/>
</bean>
This solution runs.
:)
Better add both files - in general, making test/production or debug/profile/production distinction in build makes only trouble.
Better try to use different perasistence unit name for production (say abc-production) and for tests (abc-tests).

Categories