Customized ConsoleAppender in Eclipse RCP gives circular dependencies - java

I'm working on a Eclipse RCP application, and I would like to have a customized ConsoleAppender, so I can redirect all logs to the log window.
The log4j plugin and the log4j fragment (containing the log4j.properties) creates a unit which I manage to use successfully.
I've also created an 'extension' plugin containing my code to capture the log-data. Behold the 2 plugins and the fragment below.
rcp_external_log4j (plugin containing the jar file)
log4j-1.2.16.jar
rcp_external_log4j_fragment (containing the log4j.properties file)
log4j.properties (which points to VirtualConsol)
rcp_external_log4j_extension (plugin containing the VirtualConsol)
src/VirtualControl.java (which extends ConsoleAppender)
When I execute my project from within the Eclipse debug environment everything works fine. The VirtualConsole forwards all logging data as expected.
However, when I try to export the project with the 'Eclipse product export wizard' to a standalone executable I get the following problem:
Problem Occured
'Export Product' has encountered a problem.
A cycle was detected when generating the classpath
rcp_external_log4j_extension
rcp_external_log4j
rcp_external_log4j_extension
The VirtualConsole extends ConsoleAppender and is also called from other parts of the code.
The VirtualConsole is located in rcp_external_log4j_extension and uses log4j due to the extending of ConsoleAppender.
The rcp_external_log4j uses the rcp_external_log4j_extension, due to that the rcp_external_log4j plugin is bundled with the rcp_external_log4j_fragment, which refers to the VirtualConsole in the log4j.properties file.
Question: How can I write my own ConsoleAppender without getting a circular dependency? Can I put the code in the fragment? Can I put the code in the plugin containing the jar file (rcp_external_log4j)? I've tried those 2 attempts but without success...
Grateful for any help
Problem solved. src is put in the same plugin as the jar file.
rcp_external_log4j (plugin containing the jar file)
log4j-1.2.16.jar
src/VirtualControl.java (which extends ConsoleAppender)
rcp_external_log4j_fragment (containing the log4j.properties file)
log4j.properties (which points to VirtualConsol)
and 'src' added to the classpath of rcp_external_log4j. Seen in the MANIFEST.MF as
Bundle-ClassPath: log4j-1.2.16.jar,
src/
This way the VirtualConsole may be used both from the fragment and from the other code.
And the build.properties should contain:
jars.compile.order = src/
source.src/ = src/
output.src/ = bin/
for the code to be included in the exported product.

I don't think rcp_external_log4j_fragment needs to have rcp_external_log4j_extension in its build path, only in the manifest. This should remove the cycle.

Related

How do I build an OpenFire plugin using Gradle in Intellij?

According to the OpenFire documentation (https://www.igniterealtime.org/builds/openfire/docs/latest/documentation/plugin-dev-guide.html) to build a custom plugin I need to create a jar with the following folder structure:
myplugin/
|- plugin.xml <- Plugin definition file
|- readme.html <- Optional readme file for plugin, which will be displayed to end users
|- changelog.html <- Optional changelog file for plugin, which will be displayed to end users
|- logo_small.gif <- Optional small (16x16) icon associated with the plugin (can also be a .png file)
|- logo_large.gif <- Optional large (32x32) icon associated with the plugin (can also be a .png file)
|- classes/ <- Resources your plugin needs (i.e., a properties file)
|- database/ <- Optional database schema files that your plugin needs
|- i18n/ <- Optional i18n files to allow for internationalization of plugins.
|- lib/ <- Libraries (JAR files) your plugin needs
|- web <- Resources for Admin Console integration, if any
|- WEB-INF/
|- web.xml <- Generated web.xml containing compiled JSP entries
|- web-custom.xml <- Optional user-defined web.xml for custom servlets
|- images/
I know there is an Ant build script to help do this but I couldn't find it and I'm having a hard enough time with Gradle and Maven, I'd rather not add having to learn Ant and deal with XML on to my list of chores. So, I tried to make a Gradle build script. Unfortunately Gradle still doesn't make any sense to me and in Intellij it seems to just do whatever it wants.
Regardless, this is the Gradle script I came up with.
task buildPluginJar {
group 'build'
description 'Builds OpenFire Plugin Jar'
println 'Clean old libs and classes.'
delete 'pluginDefinition/lib/*'
delete 'pluginDefinition/classes/*'
println 'Copy libs.'
copy {
into 'pluginDefinition/lib'
from configurations.runtime
}
println 'Copy classes.'
copy {
into 'pluginDefinition/classes'
from 'build/classes'
}
println 'Build jar.'
String outputPath = 'build/out/' + project.name + '.jar';
jar {
into outputPath
from fileTree('pluginDefinition/').include('**/*').collect { zipTree it }
}
}
I managed to get the file copying to work, but the end where it's supposed to put it all into a signal jar isn't working. It completes but there is no jar output. What am I doing wrong?
I could not figure out how to do this with Gradle. But I did figure out how to build jars with Intellij. I followed this tutorial:
http://blog.jetbrains.com/idea/2010/08/quickly-create-jar-artifact/
I went through the File > Project Structure menu and added two artifacts. One to build the jar with all of the java code in my pluginDefinition/lib folder, and another to build a jar with the full contents of the pluginDefinition folder that I could install on my Openfire server.
Still, it would have been nice if I could have done this with Gradle.

log4j2.xml and log4j2-test.xml in eclipse

I have these two log files on my eclipse classpath, in src/main/resources and src/test/resources respectively.
The problem is that log4j2-test.xml is higher priority and is always the chosen configuration file when running my application. How do I tell eclipse to ignore log4j2-test.xml and use log4j2.xml when running my application and to fall back to log4j2-test.xml when running unit tests?
Just for the case that somebody had still some major trouble like me.
A working solution is:
create a plugin MyLog4J that contains and provides the log4j jar files.
add "Eclipse-BuddyPolicy: registered" the Manifest.MF of the MyLog4J plugin
in your plugin that defines your actual application (e.g. Entrypoint) put log4j2.xml in the src folder
AND add "Eclipse-RegisterBuddy: MyLog4J" to it's Manifest.MF
That Eclipse-RegisterBuddy is the key step to allow log4j to find the log4j2.xml file during startup!
Now you can re-use the MyLOG4J plugin in all your projects and have an individual log4j2.xml file for each application.
You can execute this below statement in junit setup() method.This file should be avilable in the same package where your running this or you can provide the full path for this file.
PropertyConfigurator.configure("log4j2-test.xml");
In log4j2 you can write the following
org.apache.logging.log4j.LogManager ctx = (org.apache.logging.log4j.LogManager) LogManager.getContext(true);
ctx.setConfigLocation(LoggerTest.class.getClassLoader().getResource("log4j2-test.xml").toURI());
assuming log4j2-test.xml is in your classpath.

Filepath in war

I created sigleton ApplicationConfig for settigs, that reads xml config file. But every time it fails on path to file.
hierarchy:
META-INF
src
--application
----config.xml
--engine
----ApplicationConfig
web
--WEB-INF
----web.xml
I've tried File f = new File("../application/config.xml"); but it gives C:\WebLogic\application\config.xml
It's usually a bad idea to store your configs in 'src'. It's better to separate your code and configuration. I suggest you to read about maven (or gradle).
Basic maven app has pretty simple structure:
src
--main
----java
----resources
where in 'java' folder you store your code, and in the 'resource' folder you store your configs. And now you have problem, because jvm is trying to find your file relatively WebLogic base folder.
And if you use maven, you could just write:
ApplicationConfig.class.getResourceAsStream("/config.xml")
Of course, in this case you should put your config into 'resources' folder.

Log4J properties file not found

I have a Java Project that was added to the Java Build Path of a Web Project.
On the first Java project I added the Log4J JAR file to the Java Build Path and since this project was added to the Java Build Project of the Web Project, the JAR file was automatically added to the Web Project Java Build Path also.
On the Web Project I have a Web Service that instantiates a class of the Java Project. That class has a simple Logger, and it works correctly.
Now, I am trying to create a properties file named log4j.properties to configure the Logger, Appender and LayoutPattern.
Whenever I try to call a method of the instantiaded class I get this error on the console:
log4j:ERROR Could not read configuration file [log4j.properties].
What am I doing wrong?
Here's the log4j properties file:
log4j.rootLogger=DEBUG, CA
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
Sorry but it was a false alarm...
Like I said, the project where the class that instantiates the logger resides is added as a dependency o a main project where the web services are defined.
As a result that project is published on a JAR file and with the suposed solution I mentioned:
PropertyConfigurator.configure(getClass().getProtectionDomain().getCodeSource().getLocation().getPath() + "log4j.properties");
I get a path like:
C:/project_path.jar/log4j.properties.
Obviously the propertied files still isn't found...
Sory... Still working on a solution
If using log4j 2.x, you need to have a file called log4j2.xml.
log4j.properties won't do it.
Place your log4j.properties file in your classes directory if using unpacked WAR, else place it in the src folder (root folder for your java classes).
The only way I found to solve this was to put the log4j.properties file in the src root folder.
Then on the class that instantiates the logger the following line:
PropertyConfigurator.configure("log4j.properties")
... had to be changed to:
PropertyConfigurator.configure(getClass().getProtectionDomain().getCodeSource().getLocation().getPath() + "log4j.properties");
And finally the file was found.
Thanks for the insight Pål
Ok, sometimes the obvious answer is the one you least expect.
As it turned out I simply needed to remove the PropertyConfigurator.configure(xxx) line and place the log4j.properties file on the src folder of the dependency project.
Thanks

Where should I put the log4j.properties file?

I wrote a web service project using netbeans 6.7.1 with glassfish v2.1, put log4j.properties to the root dir of project and use:
static Logger logger = Logger.getLogger(MyClass.class);
in Constructor:
PropertyConfigurator.configure("log4j.properties");
and in functions:
logger.info("...");
logger.error("...");
// ...
but, it is error info(actually, I have tried to put it almost every dir that I could realize):
log4j:ERROR Could not read configuration file [log4j.properties].
java.io.FileNotFoundException: log4j.properties (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:106)
at java.io.FileInputStream.<init>(FileInputStream.java:66)
at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:297)
at org.apache.log4j.PropertyConfigurator.configure(PropertyConfigurator.java:315)
at com.corp.ors.demo.OrsDemo.main(OrisDemo.java:228)
log4j:ERROR Ignoring configuration file [log4j.properties].
log4j:WARN No appenders could be found for logger (com.corp.ors.demo.OrsDemo).
log4j:WARN Please initialize the log4j system properly.
the example project could be get from http://www.91files.com/?N3F0QGQPWMDGPBRN0QA8
I know it's a bit late to answer this question, and maybe you already found the solution, but I'm posting the solution I found (after I googled a lot) so it may help a little:
Put log4j.properties under WEB-INF\classes of the project as mentioned previously in this thread.
Put log4j-xx.jar under WEB-INF\lib
Test if log4j was loaded: add -Dlog4j.debug # the end of your java options of tomcat
Hope this will help.
rgds
As already stated, log4j.properties should be in a directory included in the classpath, I want to add that in a mavenized project a good place can be src/main/resources/log4j.properties
You can specify config file location with VM argument -Dlog4j.configuration="file:/C:/workspace3/local/log4j.properties"
You have to put it in the root directory, that corresponds to your execution context.
Example:
MyProject
src
MyClass.java
log4j.properties
If you start executing from a different project, you need to have that file in the project used for starting the execution. For example, if a different project holds some JUnit tests, it needs to have also its log4j.properties file.
I suggest using log4j.xml instead of the log4j.properties. You have more options, get assistance from your IDE and so on...
For a Maven Based Project keep your log4j.properties in src/main/resources. Nothing else to do!
If you put log4j.properties inside src, you don't need to use the statement -
PropertyConfigurator.configure("log4j.properties");
It will be taken automatically as the properties file is in the classpath.
Try:
PropertyConfigurator.configure(getClass().getResource("/controlador/log4j.properties"));
The file should be located in the WEB-INF/classes directory.
This directory structure should be packaged within the war file.
My IDE is NetBeans. I put log4j.property file as shown in the pictures
Root
Web
WEB-INF
To use this property file you should to write this code:
package example;
import java.io.File;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.Logger;
import javax.servlet.*;
public class test {
public static ServletContext context;
static Logger log = Logger.getLogger("example/test");
public test() {
String homeDir = context.getRealPath("/");
File propertiesFile = new File(homeDir, "WEB-INF/log4j.properties");
PropertyConfigurator.configure(propertiesFile.toString());
log.info("This is a test");
}
}
You can define static ServletContext context from another JSP file.
Example:
test.context = getServletContext();
test sample = new test();
Now you can use log4j.property file in your projects.
A few technically correct specific answers already provided but in general, it can be anywhere on the runtime classpath, i.e. wherever classes are sought by the JVM.
This could be the /src dir in Eclipse or the WEB-INF/classes directory in your deployed app, but it's best to be aware of the classpath concept and why the file is placed in it, don't just treat WEB-INF/classes as a "magic" directory.
I've spent a great deal of time to figure out why the log4j.properties file is not seen.
Then I noticed it was visible for the project only when it was in both MyProject/target/classes/ and MyProject/src/main/resources folders.
Hope it'll be useful to somebody.
PS: The project was maven-based.
I found that Glassfish by default is looking at [Glassfish install location]\glassfish\domains[your domain]\ as the default working directory... you can drop the log4j.properties file in this location and initialize it in your code using PropertyConfigurator as previously mentioned...
Properties props = System.getProperties();
System.out.println("Current working directory is " + props.getProperty("user.dir"));
PropertyConfigurator.configure("log4j.properties");
Your standard project setup will have a project structure something like:
src/main/java
src/main/resources
You place log4j.properties inside the resources folder, you can create the resources folder if one does not exist
I don't know this is correct way.But it solved my problem.
put log4j.properties file in "project folder"/config and use PropertyConfigurator.configure("config//log4j.properties");
it will works with IDE but not when run the jar file yourself.
when you run the jar file by yourself just copy the log4j.properties file in to the folder that jar file is in.when the jar and property file in same directory it runs well.
Put log4j.properties in classpath.
Here is the 2 cases that will help you to identify the proper location-
1. For web application the classpath is /WEB-INF/classes.
\WEB-INF
classes\
log4j.properties
To test from main / unit test the classpath is source directory
\Project\
src\
log4j.properties
There are many ways to do it:
Way1: If you are trying in maven project without Using PropertyConfigurator
First:
check for resources directory at scr/main
if available,
then: create a .properties file and add all configuration details.
else
then: create a directory named resources and a file with .properties
write your configuration code/details.
follows the screenshot:
Way2: If you are trying with Properties file for java/maven project Use PropertyConfigurator
Place properties file anywhere in project and give the correct path.
say: src/javaLog4jProperties/log4j.properties
static{
PropertyConfigurator.configure("src/javaLog4jProperties/log4j.properties");
}
Way3: If you are trying with xml on java/maven project Use DOMConfigurator
Place properties file anywhere in project and give correct path.
say: src/javaLog4jProperties/log4j.xml
static{
DOMConfigurator.configure("src/javaLog4jProperties/log4j.xml");
}
For me, it worked when I put the file inside the resources folder.
Also, it was a war file for my project. My recommendation is to ensure that the name of the file is log4j.properties, as my project didn't recognize "log4j2.properties"
Actually, I've just experienced this problem in a stardard Java project structure as follows:
\myproject
\src
\libs
\res\log4j.properties
In Eclipse I need to add the res folder to build path, however, in Intellij, I need to mark the res folder as resouces as the linked screenshot shows: right click on the res folder and mark as resources.
You don't need to specify PropertyConfigurator.configure("log4j.properties"); in your Log4J class, If you have already defined the log4j.properties in your project structure.
In case of Web Dynamic Project: -
You need to save your log4j.properties under WebContent -> WEB-INF -> log4j.properties
I hope this may help you.
Open spark-shell
Then type System.getenv("SPARK_CONF_DIR")
That will print where your log4j.properties should go.

Categories

Resources