Configuring log4j2 in a multi-module J2EE web project without maven - java

I've been searching the web and SO for a while now to find the answer for my question, but everything I could find addressed multi-module projects that were implemented with Maven. My project does not use maven and so it doesn't help my scenario.
I'm building a Java 8 J2EE web services project that runs on Tomcat 8 and is broken into a few separate projects (see project tree below). I am not using maven, I'm defining all of the dependencies through eclipse (I am hoping to learn about maven at some point and "mavenize" my projects, but I'm not there yet).
How can I achieve the following:
Have a single log4j2.xml file that would be used by the dynamic web project and all the Java sub-projects. The only thing that has worked for me so far is to have a copy of the log4j2.xml file present in the src folder of each of the projects.
I've attempted various things, such as placing the configuration file in a shared folder and adding the folder to each of the projects' class path, or placing the file in the CommonLib project, which is used by all, but each time I keep getting a log4j warning that no configuration file was found.
Here's my project tree:
Services (Dynamic web project)
^
|__ BusinessCore (Java project)
| ^
| |___ DAO (Java project)
| | ^
|_________|_____|__CommonLib (Java project)

It sounds like you're trying to use log4j2 automatic configuration by including the log4j2 config file on the classpath.
I further assume that you're trying to run your code from within Eclipse. The only way it will work correctly with automatic configuration (without specifying the path to the config file via system property) is if the log4j2 config file is inside of a "source folder" that is included on the build path or if you put your config file inside of a jar and add that jar to your build path.
So, assuming you're using a log4j2.xml file, if you place log4j2.xml inside of a source folder of your CommonLib project and include this project on the build path of your other projects (along with the necessary log4j2 jars) it should work fine.
Here is how I have set up an example project:
Content of root level project folder non-maven-web-project-log4j2:
Content of BusinessCore:
Content of CommonLib:
Note that the "config" folder is a source folder (you will see this again later) in Eclipse and that the log4j2.xml is contained in the config folder.
Build Path configuration:
non-maven-web-project-log4j2 has a dependency on the BusinessCore project
BusinessCore has a dependency on CommonLib (no screenshot, it's almost identical to the previous)
CommonLib has an extra source folder called config:
and this config folder contains the log4j2.xml file:
Each project has one simple class in its source folder that references a class from its child project. In the non-maven-web-project-log4j2 project there is a class that refers to the class in BusinessCore, and in BusinessCore there is a class referring to the class in CommonLib. Every class generates a log4j2 message. When I run the class from the root project (non-maven-web-project-log4j2) I am able to see all of the logs and the logs have the pattern I specified in my log4j2 config file which confirms that log4j2 is able to find its configuration.
As a final note - I added the extra "config" source folder just to emphasize the point that you can place your log4j2 config file in any source folder in the build path, it is not necessary to create a separate folder for it if you don't want to - you could instead just include it in the src directory as you already noted in your question.

Related

java relative file path issue in dependant projects

I've a maven project called Project_1. In this project I've a file reader which reads a config file(using relative path) from resources folder(which is sourced) of this project. I've another maven project called Project_2 in which Project_1 is added as dependency. When I'm running the Project_2 now, the relative path for reading config file is not working as ClassPath is set based on Project_2. Could anyone please help me to use proper file path which works in any condition.
NOTE: I don't want to use absolute file path, as I want these projects to be portable. Project_2 alone is customer facing and config file is specific to Project_1 which is not allowed to be configured by customer facing application.

ClassNotFoundException when using a self-created jar file

Using Eclipse I created some parser classes I want to provide to another project as a jar archive for validation purposes. So the parser project look like this:
ParserProject
- src
-- com.package.x
--- ClassA
--- ClassB
- lib
-- external1.jar
-- external2.jar
The ClassA and ClassB use the external jar archives, like Jackson or some Apache commons. To provide the functionality to another project, I exported the entire project as jar archive and executable jar archive (Right click on project > Export... > Java > JAR file > Select all files and "Export generated class files and resources" > Finish).
The jar file is created without any errors. When I use the parserproject.jar in my validation project, I can access all my methods using auto completion, but when I run the validation project, I get a java.lang.ClassNotFoundException: com.fasterxml.jackson.core.JsonParseException.
Now three strange things:
All jackson jars are included in the parser project. Besides, I can run a main() method in the parser project and everything works fine, no ClassNotFoundException occurs.
When I add the parserproject.jar to my validation project in the class path and open the jar archive in the Package Explorer, the parserproject.jar seems to contain all jars it needs.
For the executable jar archive, all required external jars are contained in the MANIFEST.MF (Package Explorer > validation project > Referenced Libraries > + besides parserproject.jar > META-INF > MANIFEST.MF). It looks like this:
Manifest-Version: 1.0
Rsrc-Class-Path: ./ json-20140107.jar jackson-annotations-2.5.4.jar ja
ckson-core-2.5.4.jar jackson-databind-2.5.4.jar commons-io-2.4.jar co
mmons-validator-1.3.1.jar slf4j-api-1.7.5.jar slf4j-log4j12-1.7.5.jar
json-schema-validator-2.2.6.jar jackson-module-jsonSchema-2.4.4.jar
juniversalchardet-1.0.3.jar snakeyaml-1.15.jar commons-beanutils-1.7.
0.jar commons-digester-1.6.jar commons-logging-1.0.4.jar joda-time-2.
8.1.jar jopt-simple-4.6.jar jsr305-3.0.0.jar json-schema-core-1.2.5.j
ar libphonenumber-6.2.jar jackson-coreutils-1.8.jar commons-lang-2.6.
jar guava-16.0.1.jar msg-simple-1.1.jar btf-1.2.jar mailapi-1.4.3.jar
uri-template-0.9.jar
Class-Path: .
Rsrc-Main-Class: com.package.SchemeValidator
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
I get the exception if and only if I use the generated jar file in my validation project. In case I get rid of the parserproject.jar and define a dependency to the ecplise parser project instead (Right click on validation project > Properties > Java Build Path > Projects) I do not get the ClassNotFoundException.
So now my question is, how I should export the jar so that every class is found. Thank you!
Eclipse only takes care of the compile-time dependencies while generating a .jar
Since your generated .jar can be moved to virtually anywhere, the dependencies must again be present during execution time.
You have two options:
Execute your jar with the -jar option, while leaving all
dependencies in the same folder. Since your manifest uses "./" as classpath, this means all dependencies must be on the same directory you are executing your jar from. NOTE classpath is relative to the directory you are executing from, not the directory the file is on.
Execute your jar withour the -jar option, and specify the -cp option to point to the dependencies, and the specify the main class.
java -cp "<path to your jar>;<path to dependency 1>;<path to dependency 3>[;...]" <your main class>
You might consider creating a so called fat jar which will contain all the needed classes. For example: http://fjep.sourceforge.net/
If you do not want to go through the hassle of managing all the depencencies by yourself, consider using a build tool like
Maven https://maven.apache.org/ or Gradle https://gradle.org/.

Eclipse Remote Application Platform export resource folder into WAR

I am currently writing a RAP application and would like to export a folder named "repository" containing several files along with the WAR file created by the WAR Product Configuration file. However, the resource folder is never exported into the WAR. I tried setting several BuildPaths in the the Eclipse project, the Manifest.MF and plugin.xml file. None of that worked.
Also, I also still don't know how to get a path to a contained file/folder within the resource folder on disc. I am for example trying to load a Axis2 Repository from that resource folder and my code for that is the following:
context = ConfigurationContextFactory.createConfigurationContextFromFileSystem("/repository/", "/repository/conf/axis2.xml");
yet this always throws the error that the repository could not be found in the filesystem.
Just use WAR Product Tooling plugin to create the .war file, and make sure the repository folder is put into the same project.
http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.rap.help%2Fhelp%2Fhtml%2Fadvanced%2Fdeployment.html

What's the ideal way to configure an Eclipse Web Project to test Spring/JPA

I recently used eclipse (myeclipse actually) to create a new Web Project via the new->web project wizard. The default directory structure for the project looks as follows:
src
WebRoot
WebRoot/META-INF
WebRoot/META-INF/MANIFEST.MF
WebRoot/WEB-INF
WebRoot/WEB-INF/lib
WebRoot/WEB-INF/classes (not visible via the Package/Project Explorer)
WebRoot/WEB-INF/web.xml
For jpa I added:
WebRoot/META-INF/persistence.xml
For spring I added:
WebRoot/META-INF/spring/spring-master.xml
When trying to run a very basic junit test to load the spring context and hibernate entity manager I was running into classpath problems. Initally to get around the first class path problem I encountered I added WebRoot/META-INF/spring to the junit->Run Configurations classpath when Spring couldn't find my spring configuration files.
But then I ran into another classpath error when jpa couldn't find my entity bean definition. Reading this article (dated 2007) it states that META-INF/persistence.xml should be contained within WEB-INF/classes because JPA searches for entity bean class files in the parent directory of META-INF/persistence.xml
When I copied META-INF (via Windows Explorer since eclipse is hiding the classes directory) and all its contents into WEB-INF/classes my classpath errors went away (as well as the need to monkey with the junit run configuration to remedy the previous problem of spring not knowing where my spring config file is located turns out I still need to add the spring folder to the junit classpath option).
But now I have configuration files in a folder which does not show in Eclipse's Package/Project Explorer.
What is the best way to setup Eclipse for this situation? Tell it to show the classes folder somehow? Why does Eclipse create META-INF as a sibling to WEB-INF for web projects?
Is there a way to inform JPA to look for entity classes somewhere other than the default?
Thanks for any input!
You should know that eclipse mixes the compiled classes and resource from src (and any other source code directory) in the <WebRoot>/WEB-INF/classes directory.
So one way to access the same file in Test and Webapp (for example META-INF/persistence.xml) is to put it in src/META-INF/persistence.xml. Then it is available in <WebRoot>/WEB-INF/classes/META-INF/persistence.xml for the web app, and in <classpath>/META-INF/persistence.xml for EVERY application or test.
So my recommendation is to put all the stuff that is addressed via classpath (persistence.xml, spring.xml) in a source directory, and let eclipse do the rest. - If you specify the location of a resource via classpath, then it should work the same way for webapp, test, app.
BTW: eclipse can create many source code directories, you can use one for the normal application classes, one for the class path relevant resource and one for the test classes.

Where is the correct location to put Log4j.properties in an Eclipse project?

Where in my Eclipse project should I add the log4j.properties file so that it will work as intended?
you can add it any where you want, when you run your project, configure the classpath and add the location of the log4j.properties files by clicking on:
Run->Run Configuration -> [classpath tab] -> click on user Entries -> Advanced -> Select Add Folder -> select the location of your log4j.properties file
and then -> OK -> run
and it should get loaded
The safest way IMO is to point at the file in your run/debug config
-Dlog4j.configuration=file:mylogging.properties
! Be aware: when using the eclipse launch configurations the specification of the file: protocol is mandatory.
In this way the logger will not catch any logging.properties that come before in the classpath nor the default one in the JDK.
Also, consider actually use the log4j.xml which has a richer expression syntax and will allow more things (log4j.xml tahe precedence over log4j.properties.
Add the log4j.properties file to the runtime class path of the project.
Some people add this to the root of the source tree (so that it gets copied to the root of the compiled classes).
Edit:
If your project is a maven project,
you can put the log4j.properties in the src/main/resources folder (and the src/test/resources for your unit tests).
If you have multiple environments (for example development and production),
want different logging for each environment,
and want to deploy the same jar (or war, or ear) file to each environment
(as in one build for all environments)
then store the log4j.properties file outside of the jar file and put it in the class path for each environment (configurable by environment).
Historically, I would include some known directory in each environment in the classpath and deploy environment specific stuff there.
For example,
~tomcat_user/localclasspath where ~tomcat_user is the home directory of the user that will be running the tomcat instance to which my war file will be deployed.
The best way is to create special source folder named resources and use it for all resource including log4j.properties. So, just put it there.
On the Java Resources folder that was automatically created by the Dynamic Web Project, right click and add a new Source Folder and name it 'resources'. Files here will then be exported to the war file to the classes directory
If you have a library and you want to append the log4j:
Create a folder named "resources" in your projet.
Create a .properties file named log4j
Set properties in log4j.properties file
Push right button in the project and go to properties->Java Build Path and, finally, go to the "Source" tab.
Push Add folder and search the "resources" folder created in step 1.
Finish.
(I have assumed that you have the log4j library added.)
PD: Sorry for my english.
This question is already answered here
The classpath never includes specific files. It includes directories and jar files. So, put that file in a directory that is in your classpath.
Log4j properties aren't (normally) used in developing apps (unless you're debugging Eclipse itself!). So what you really want to to build the executable Java app (Application, WAR, EAR or whatever) and include the Log4j properties in the runtime classpath.
Put log4j.properties in the runtime classpath.
This forum shows some posts about possible ways to do it.
I'm finding out that the location of the log4j.properties file depends on the type of Eclipse project.
Specifically, for an Eclipse Dynamic Web Project, most of the answers that involve adding the log4j.properties to the war file do not actually add the properties file in the correct location, especially for Tomcat/Apache.
Here is some of my research and my solution to the issue (again specifically for a Dynamic Web Project running on Tomcat/Apache 6.0)
Please refer to this article around how Tomcat will load classes. It's different than the normal class loader for Java. (https://www.mulesoft.com/tcat/tomcat-classpath) Note that it only looks in two places in the war file, WEB-INF/classes and WEB-INF/lib.
Note that with a Dynamic Web Project, it is not wise to store your .properties file in the build/../classes directory, as this directory is wiped whenever you clean-build your project.
Tomcat does not handle .property files in the WEB-INF/lib location.
You cannot store the log4j.properties file in the src directory, as Eclipse abstracts that directory away from your view.
The one way I have found to resolve this is to alter the build and add an additional directory that will eventually load into the WEB-INF/classes directory in the war file. Specifically....
(1) Right click your project in the project explorer, select 'New'->'Folder'. You can name the folder anything, but the standard in this case is 'resources'. The new folder should appear at the root level of your project.
(2) Move the log4j.properties file into this new folder.
(3) Right click the project again, and select 'Build-Path'->'Configure Build Path'. Select the 'Sources' tab. Click the 'Add Folder' button. Browse to find your new folder you created in step (1) above. Select 'OK'.
(4) Once back to the eclipse Project Explorer view, note that the folder has now moved to the 'Java Resources' area (ie it's no longer at the root due to eclipse presentation abstraction).
(5) Clean build your project.
(6) To validate that the .properties file now exists in WEB-INF/classes in your war file, export a war file to an easy location (right click Project -> Export -> War file) and checkout the contents. Note that the log4j.properties file now appears in the WEB-INF/classes.
(7) Promote your project to Tomcat/Apache and note that log4j now works.
Now that log4j works, start logging, solve world problems, take some time off, and enjoy a tasty adult beverage.
You do not want to have the log4j.properties packaged with your project deployable -- that is a bad idea, as other posters have mentioned.
Find the root Tomcat installation that Eclipse is pointing to when it runs your application, and add the log4j.properties file in the proper place there. For Tomcat 7, the right place is
${TOMCAT_HOME}/lib
In general I put it in a special folder "res" or "resources as already said, but after for the web application, I copy the log4j.properties with the ant task to the WEB-INF/classes directory. It is the same like letting the file at the root of the src/ folder but generally I prefer to see it in a dedicated folder.
With Maven, the usual place to put is in the folder src/main/resources as answered in this other post.
All resources there will go to your build in the root classpath (e.g. target/classes/)
If you want a powerful logger, you can have also a look to slf4j library which is a logger facade and can use the log4j implementation behind.
For a normal (non maven and non web) java project in eclipse.
Create a "source" folder with new options and with any name (as a standard we can name it as resources) under the project directory
push the log4j.properties file to this "source" folder.
Build and run the application.

Categories