I am trying on the associations module, and it fails because it tries to enhance the same object twice. Debugging my test case, I discover that I have two instances of both this module and less-css module loaded! It appears that the play.plugins file is loaded as two resources:
file:/C:/work/CS/portal/src/modules/associations-1.0.1/lib/play-associations.jar!/play.plugins
jar:file:/C:/work/CS/portal/src/modules/associations-1.0.1/lib/play-associations.jar!/play.plugins
This causes the pluginsToLoad variable to contain two copies of this module, and everything goes haywire from here.
Is this a mis-configuration on my part? How can I investigate further / resolve?
The module only appears once in my dependencies.yml, and does not appear in application.conf
See here for a screenshot.
Update - it seems that the classpath contains:
C:\work\CS\portal\src\modules\associations-1.0.1\src;
C:\work\CS\portal\src\modules\associations-1.0.1\lib\play-associations.jar;
And a play.plugins file exist both in the src folder, and in the jar. Now I need to understand why both are in the classpath.
This happens if you put the module into your
dependencies.yml AND declare it as module in application.conf
remove the entry in application.conf
I believe this is a bug within play idealize. I found these entries in the iml file:
<library name="Project Libraries">
<CLASSES>
<root url="file://$MODULE_DIR$/lib" />
<root url="file://$MODULE_DIR$/modules/less-0.3/src" />
<root url="file://$MODULE_DIR$/modules/associations-1.0.1/src" />
<root url="file://$MODULE_DIR$/modules/less-0.3/lib" />
<root url="file://$MODULE_DIR$/modules/associations-1.0.1/lib" />
</CLASSES>
...
I've submitted a bug (the workaround is to manually remove the /src entries)
I had the same symptom, play modules being loaded twice.
I discovered it was a bug in the "play war" 1.2-beta2 plugin that was causing my main jar file to be created twice with slightly different names and then both be included in the "WEB-INF/lib" dir of my war file.
I upgraded the plugin to the latest 1.2-beta4 and it seems to have been fixed
Related
With Weblogic 11g I have done the following:
1 Created log4j.xml file where I created a new appender:
<appender name="WEBLOGIC" class="weblogic.logging.log4j.ServerLoggingAppender">
<param name="Threshold" value="ERROR"/>
</appender>
<root>
<priority value="WARN"/>
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="WEBLOGIC"/>
</root>
2 Updated the ${DOMAIN_HOME}/bin/setDomainEnv.sh script with these changes:
LOG4J_CONFIG_FILE="${DOMAIN_HOME}/config/log4j.xml"
if [ "${LOG4J_CONFIG_FILE}" != "" ] ; then
JAVA_PROPERTIES="${JAVA_PROPERTIES} Dlog4j.configuration=file:${LOG4J_CONFIG_FILE}"
export JAVA_PROPERTIES
fi
JAVA_OPTIONS="${JAVA_OPTIONS} ${JAVA_PROPERTIES} -Dweblogic.log.Log4jLoggingEnabled=true -Dwlw.iterativeDev=${iterativeDevFlag} -Dwlw.testConsole=${testConsoleFlag} -Dwlw.logErrorsToConsole=${logErrorsToConsoleFlag}"
3 Copied the log4j jars to the domain/lib
cp ./wlserver_10.3/server/lib/wllog4j.jar user_projects/domains/my_domain/lib/
cp ./wlserver_10.3/server/lib/consoleapp/APP-INF/lib/log4j-1.2.8.jar user_projects/domains/my_domain/lib/
4 Starts the AdminServer, but I get this error:
java.lang.ClassCastException:
weblogic.logging.log4j.ServerLoggingAppender cannot be cast to
org.apache.log4j.Appender
Keep step 1 and remove changes done in other steps.
Now copy the log4j.xml to $DOMAIN_HOME/lib folder. This will keep your log4j.xml in the server's classpath and the server will use this log4j.xml as its log4j configuration. No additional changes are required.
In setDomainEnv.xml file, please add the set log4j.xml location as below:
set LOG4J_CONFIG_FILE=C:\bea\user_projects\domains\dev\lib\log4j.xml
if NOT "%LOG4J_CONFIG_FILE%"=="" (
set JAVA_PROPERTIES=%JAVA_PROPERTIES% -Dlog4j.configuration=file:%LOG4J_CONFIG_FILE%
)
What you have to see is if despite the warning that you get, if the ServerLogging is effectively not working on your appliction on your domain.
Probably not even there since you are only copying the log4j to the domain/lib folder but not the wllog4j.jar.
So your setup looks like is doomed not to work in any case.
To me, It looks to me that you are undergoing Class Loader Vodoo Messup.
(1) You set a global log4j properties file for the entire app server.
(2) it looks like weblogic console app is itself a ear and it bundles its own LOG4J implementation library, which you are copying into your domain.
When the console app runs, it must for sure make use of Log4j and the class loader loading the Log4j Appender definition is most likely a level lower than the class loader that knows about the ServerLoggin bridge adapter.
I am beting its for reason like this that weblogic is geting rid of LOG4j in future gnerations of the product.
They have too many class loader issues - JUL logging you have the APP class loader behind the core classes - such as Handlers/Adapters.
Anyway.
(3) When weblogic runs, namley when it bootstraps the console it probably runs some sort class loader that gives a level of isolation to the libs bundled in the applicaiton and it sees:
Oh! How nice, LOG4j is here, leets initialize it.
Second, LOG4j bootstraps and hits head on your log4j.properties where you put the server logging appender in there - cross cutingly for everybody (including the weblogic application console).
He goes hunting for this library and where does it find it?
One of them, the wllog4j.jar he finds somewhere in the weblogic generic container libraries. While the base core classes of Log4j he finds a level lower in the domain configuration or in the EAR configuraiton of the console applicaiton.
This is not good.
Try the following:
(a) go into the weblogic console app, go to the Meta Inf folder and re-write the weblogi-application.xml
It will have a prefer applicaiton packages that looks like this:
org.apache.log4j.*</package-name--> <---- here I've commented this line.
If you comment the above line, the application class loader will search for log4j libraries in the highest parent that knows about these classes.
So if you put at the same level where your ServerLogger is found you should be fine.
(b) Pug the log4j implementation library at the same level where the wllog4j.jar will be found.
Check if you still get the casting exceptions.
Be very careful when you make server wide cross cuting configurations.
Good luck.
For some applications I use ZK, others Hibernate, other Apache Commons, etc.
I don't want to deploy a 75MB war file, just because it uses lots of libraries.
I don't want to add the libraries to my tomcat lib folder, or nor the classpath to it's configuration as I may have an old application using library x.1 and another application using library x.2
For this reason, it would be great to have something in the web.xml or context.xml where I say something like:
<classpath>/usr/local/tomcat/custom-libs/zk-5.0.4</classpath>
Note: The above is pseudo-code
From Tomcat 7 there is no mention of not being able to use the VirtualWebappLoader in production. I tried it and it works like a dream. Simply add the following to META-INF/context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/websandbox">
<Loader className="org.apache.catalina.loader.VirtualWebappLoader"
virtualClasspath="/usr/.../*.jar;/usr/.../*.jar"/>
</Context>
In Netbeans, under packaging, I just untick all the packages, taking the .war size down to nothing, make sure the dependencies are in the correct folders on the server and upload. Yey! No more 100 MB WAR file.
Addition #Spider answer.
Tomcat 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!!!
Here my config which demonstrate how to use development version of project files out of $CATALINA_BASE hierarchy (note that I place this file into src/test/resources dir and intruct Maven to preprocess ${basedir} placeholders through pom.xml <filtering>true</filtering> so after build in new environment I copy it to $CATALINA_BASE/conf/Catalina/localhost/$APP.xml):
<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"/>
<!-- Use development version of JS/CSS files. -->
<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>
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>
Another a bit hacky alternative.
You can write a 5-6 line custom class loader which derives from urlclassloader, and simply adds your classpath jars using addUrl() method.
Then set it as the context class loader of the thread in your application code.
Thread.setContextClassLoader(new CustomClassloader(path, parentClassLoader)
where parent class loader typically is
Thread.getContextClassloader()
This is what the META-INF/context.xml file can be used for. You defined your own WebappLoader, which loads classes for your particular webapp. This is the reference I used: http://tomcat.apache.org/tomcat-5.5-doc/config/loader.html (Edit: for Tomcat 6: http://tomcat.apache.org/tomcat-6.0-doc/config/loader.html, for Tomcat 7: http://tomcat.apache.org/tomcat-7.0-doc/config/loader.html)
Also this fellow here seems to post a solution to your exact problem (example included): http://java.dzone.com/articles/extending-tomcat-webapploader
I am starting up a Seam + Hibernate + Logback project deployed to Tomcat 6. I use Eclipse as an IDE. Hibernate prints many debug statements, so I have put the level to ERROR, so I don't see them.
<logger name="org.hibernate">
<level value="ERROR" />
</logger>
I don't paste my whole logback.xml, because the problem I have, is not connected with its contents.
I have the following classpath problem - If I put the logback.xml in WEB-INF\classesof my project, it is not found by the classloader and I see all debug statements. On the other hand, if I move the logback.xml to the lib directory of Tomcat, everything works perfect and the debug statements are not printed.
But I want to have my logback.xml inside my project, not in the root lib directory of Tomcat.
And here is my question - isn't the WEB-INF\classes a correct place for logback.xml? Why isn't it found?
I have always known that the files under the WEB-INF\classes directory of the project, are put to the classpath. Thank you for any ideas you have.
All the best, Petar
It looks like your logback.jar is also under ${catalina.home}\lib.
If you want to put your logback.xml to \WEB-INF\classes, the logback.jar should be only under \WEB-INF\lib. The ${catalina.home}\lib\logback.jar should be removed.
I have an EAR that is made up of two modules. Both expose services and share common code.
Imagine that the ear has a common.jar shared by a webservices.war and webapp.war.
I use log4j to log the activities. I would like to be able to have two log files (webservices.log and webapp.log) capturing the events that are specific to each of them plus all the stuff that is handled by the common.jar.
How should I configure my categories and my appenders to achieve this?
At the moment I have the following packages:
com.myapp for shared stuff
com.myapp.webservices for the webservices and
com.myapp.webapp for the webapp.
My problem is that I don't know how I can capture the com.myapp (common stuff) in both log files by using a single log4j configuration file.
I have tried setting up multiple configuration files but when JBoss would work OK Websphere would break and the other way round...
Thank you
You can keep log4j configuration anywhere you like, just make sure Logger is able to initialize the engine from the configuration file. I don't see any reason why one configuration file is not working for both Jboss and WebSphere. Could you be more specific on what is breaking?
You need to configure two file appenders named webservices and webapp in same log4j configuration files and using the package names redirect to the relevant appender.
<logger name="com.myapp.webservices">
<appender-ref ref="webservices" />
</logger>
<logger name="com.myapp.webapp">
<appender-ref ref="webapp" />
</logger>
I have a JEE application that runs on WAS 6. It needs to have the class loader order setting to "Classes loaded with application class loader first", and the WAR class loader policy option set to "Single class loader for application".
Is it possible to specify these options inside the EAR file, whether in the ibm-web-bnd.xmi file or some other file, so the admin doesn't need to change these setting manually?
Since the app is deployed via an automated script, and the guy who is in charge of deployment is off site, and also for some other political reasons, this would greatly help!
Thanks to #Matthew Murdoch's answer, I was able to come up with a solution. Here it is, in case it helps someone else.
I created a deployment.xml like this:
<?xml version="1.0" encoding="UTF-8"?>
<appdeployment:Deployment xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:appdeployment="http://www.ibm.com/websphere/appserver/schemas/5.0/appdeployment.xmi" xmi:id="Deployment_1241112964096">
<deployedObject xmi:type="appdeployment:ApplicationDeployment" xmi:id="ApplicationDeployment_1241112964096" startingWeight="1" warClassLoaderPolicy="SINGLE">
<classloader xmi:id="Classloader_1241112964096" mode="PARENT_LAST"/>
<modules xmi:type="appdeployment:WebModuleDeployment" xmi:id="WebModuleDeployment_1241112964096" startingWeight="10000" uri="AGS.war">
<classloader xmi:id="Classloader_1241112964097"/>
</modules>
</deployedObject>
</appdeployment:Deployment>
Make sure to change the name of your WAR file(s) to match (mine is called AGS.war).
I also changed the numbers in the xmi:id attributes, to be sure they are unique, though I'm not sure it it really matters that they be unique across applications.
Then, I put the deployment.xml file in the root of my EAR file, via ANT:
<ear destfile="${artifactsDir}/${earName}.ear" appxml="${projectName}_EAR/application.xml">
<fileset dir="${artifactsDir}" includes="${warName}.war"/>
<fileset dir="${projectName}_EAR/" includes="deployment.xml"/>
</ear>
Edit (2): The WebSphere Application Server Toolkit (AST) is a tool you can use to enhance an EAR file with this information (see for example the 'Configure an Enhanced EAR' section in this document).
Edit (1): This post suggests that the 'Classes loaded with application class loader first' (the PARENT_LAST setting) can be set in the deployment.xml file within the EAR.
If you have control over the automated deployment scripts this can be done. Below is some wsadmin jython code for setting the web module class loader order to 'Classes loaded with application class loader first' (interestingly the setting is called PARENT_LAST which is what it was labelled in previous versions of the admin console...).
wsadmin example (jython):
def getWebModule(config, applicationName):
webModules = config.list('WebModuleDeployment').
split(system.getProperty('line.separator'))
for webModule in webModules:
if (webModule.find(applicationName) != -1):
return webModule
return None
applicationName = "<Your application name here>"
webModule = getWebModule(AdminConfig, applicationName)
if (webModule != None):
AdminConfig.modify(webModule, "[[classloaderMode PARENT_LAST]]")
AdminConfig.save()
else:
print "Error: Cannot find web module for application: " + applicationName
Check out this link. There are different ways to set class loader policy using Jython based on your server version -
http://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=%2Fcom.ibm.websphere.express.doc%2Finfo%2Fexp%2Fae%2Frxml_7libapp4.html
Similar to the answer from pkaeding, I discovered as follows, not specific to a particular .war by name, but useful when applying to whatever is the default .war in the .ear file. (.ear files with one .war file in them have only that .war, so naming the .war isn't necessary in the entry.) This approach may be good for situations where you may need to re-name of the .war project later for some reason, and so you wouldn't need to worry about updating the deployment.xml file. I found the deployment.xml file buried inside a cell reference directory trail; dunno if it's fine as shown when the file is placed at directory level META-INF and no deeper.
In my particular case, I found deployment.xml in my .ear project at:
<project_root>\META-INF\ibmconfig\cells\defaultCell\applications\defaultApp\deployments\defaultApp\
The content of the file looks a lot like:
<appdeployment:Deployment xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:appdeployment="http://www.ibm.com/websphere/appserver/schemas/5.0/appdeployment.xmi" xmi:id="Deployment_1262775196208">
<deployedObject xmi:type="appdeployment:ApplicationDeployment"
xmi:id="ApplicationDeployment_1262775196208" startingWeight="10">
<classloader xmi:id="Classloader_1262775196208" mode="PARENT_LAST" />
</deployedObject>
</appdeployment:Deployment>
The line:
<classloader xmi:id="Classloader_1262775196208" mode="PARENT_LAST" />
originally read:
<classloader xmi:id="Classloader_1262775196208" mode="PARENT_FIRST" />
Note no reference to any .war is being made. As pkaeding mentioned, you shouldn't expect the various id numbers to be the same for you.