I'm logging in a JSF and ejb enviroment and every time I redeploy my app, the .lck files don't get deleted and a new log (and lock) file is created (logfilename.log.2, logfilename.log.3 ...)
This is how I get the log and add a filehandler in a JSF managed bean:
static {
// (...)
logger = Logger.getLogger("registrations");
FileHandler fh;
try {
// (...)
fh = new FileHandler(registerLogPath, true);
fh.setFormatter(new Formatter() {
#Override
public String format(LogRecord record) {
return ...
}
});
logger.addHandler(fh);
} catch (IOException | SecurityException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
I tried to remove the handlers in the contextDestroyed method of ServletContextListener, but it seems that it is too late since Logger.getLogger("registrations").getHandlers() returns an empty array, so nothing to remove.
Can you help me how to make the logger use the file it used before redeploying?
I finally managed to solve this. Removing a handler is not enough, you have to call close() on the handler itself. Also, logger.getHandlers() works in a contextDestroyed method:
for (Handler h : logger.getHandlers()) {
h.close();
}
Related
I am trying to shut down my application ( which is a jar and is run manually)
I have read this : http://forum.spring.io/forum/spring-projects/container/98741-how-to-applicationcontext-memory-leaks-in-spring-3-0-x
Spring ApplicationContext - Resource leak: 'context' is never closed
and as i am using the spring 3.2.18
my code looks like
private static ConfigurableApplicationContext parentContext ;
private static ConfigurableApplicationContext processContext ;
private final String processApplicationContextChild; // filename: childContext.xml
public void run() {
log.debug("Loading parent context");
parentContext = new ClassPathXmlApplicationContext("applicationContext.xml") ;
parentContext.registerShutdownHook();
try {
runProcess(parentContext);
} catch (Throwable e) {
log.error("Unexpected error: " + e.getMessage(), e);
} finally {
log.info("Closing Core Context ");
if (parentContext.isActive()){
parentContext.close();
}
log.info("Core Closed");
}
}
protected void runProcess(ConfigurableApplicationContext parentContext) {
log.info("Loading " + Arrays.asList(processApplicationContextChild));
processContext = new ClassPathXmlApplicationContext(processApplicationContextChild, parentContext);
processContext.registerShutdownHook();
Runnable processor = (Runnable) processContext.getBean("processorRunnable", Runnable.class);
try {
processor.run();
} finally {
log.info("Closing child Context ");
processContext.close();
log.info(" Child Closed");
}
}
After the "Core Closed" is printed out. it just hangs and does nothing. I am expecting the JVM to exit.
There is some resource some where either the child or parent which is not closed properly. how can i view that resource. Or what could be the issue here.
when i debug, on each .close() call, the context is still an instance with closed=true and isActive=false.
I even made them non static and used a try with resource block.
The issue was a resource leak the solution of which is described here
RestEasyClient JAX RS possible resource leak if not done correctly
I try to load a property file in Java running on JBossFuse/karaf.
The file is located at $[karaf.home]/etc/bean.properties
The Code is able to load properties inside the bundle fine, but now I try to exclude the properties from the project itself and the code throws a Nullpointer-Exception.
The Path is properly resolved on my development machine as
C:\Users\someone\devstudio\runtimes\jboss-fuse-6.3.0.redhat-135\etc\bean.properties
The property-File can be loaded in the blueprint-XML to configure beans, but to access the bean my code needs the CamelContext. As I have some static codeblocks that are accessed without an exchange/context/registry, I also wanted to be able to load the properties in Java.
Both the functions throw the NullPointerException and I guess, it is because the code runs in Fuse.
public static Properties getProperties(String location) {
Properties prop = new Properties();
InputStream input = null;
try {
input = PropertyLoader.class.getClassLoader().getResourceAsStream(location);
prop.load(input);
} catch (IOException ex) {
log.error("Error loading properties file from: " + location, ex);
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
log.error(e);
}
}
}
return prop;
}
public static Properties getPropertiesFromFilesystem(String location) {
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream(location);
prop.load(input);
} catch (IOException ex) {
log.error("Error loading properties file from: " + location, ex);
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
log.error(e);
}
}
}
return prop;
}
The Exception:
java.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Properties.java:434)[:1.8.0_91]
at java.util.Properties.load0(Properties.java:353)[:1.8.0_91]
at java.util.Properties.load(Properties.java:341)[:1.8.0_91]
at com.mycompany.util.PropertyLoader.getProperties(PropertyLoader.java:19)[319:camel-archetype-blueprint:0.0.14]
at com.mycompany.camel.blueprint.MyProcessor.process(MyProcessor.java:21)[319:camel-archetype-blueprint:0.0.14]
at org.apache.camel.processor.DelegateSyncProcessor.process(DelegateSyncProcessor.java:63)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:468)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:196)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:121)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:196)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:192)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at org.apache.camel.component.timer.TimerConsumer$1.run(TimerConsumer.java:76)[231:org.apache.camel.camel-core:2.17.0.redhat-630135]
at java.util.TimerThread.mainLoop(Timer.java:555)[:1.8.0_91]
at java.util.TimerThread.run(Timer.java:505)[:1.8.0_91]
Any help would be highly appreciated.
Do not do that. You are looking for trouble.
Load properties the OSGi way (use .cfg as extension and a blueprint property-placeholder bean)
You have the added benefit of getting notified if the file changes (if you wish)
Inject them in a bean EVEN IF you are using only static methods.
Don't mix managed beans with unmanaged static code unless you know very well what you are doing.
If some "static" code requires properties means that it is stateful, and this class deserves to be instantiated to a bean.
Not sure why you are getting an NPE without a more complete example. If you need to use properties without a route, you should be using Camel's property placeholder facilities:
https://access.redhat.com/documentation/en-us/red_hat_jboss_fuse/6.3/html/apache_camel_development_guide/basicprinciples#BasicPrinciples-PropPlaceholders
I am trying to create a logs file in a Java swings application that will contain all the messages generated by the code. But unfortunately it does not create 1 single log file but creates a structure as shown. I need 1 single log file.
My code:
//get the logger object
logger = Logger.getLogger("MyLog");
try {
// This block configure the logger with handler and formatter
loggerFH = new FileHandler(System.getProperty("user.dir") + "\\resources\\logs\\logs.txt",true);
logger.addHandler(loggerFH);
SimpleFormatter formatter = new SimpleFormatter();
loggerFH.setFormatter(formatter);
} catch (IOException | SecurityException ex) {
logger.severe(ex.getMessage());
outputArea.append(ex.getMessage());
}
Your files are being rotated.
Did you try solution from this:
Java FileHandler disable log rotation
FileHandler fh = new FileHandler( "path" , 0, 1, false);
I realized my Logger file was used by several instances at a time. So when 1 instance of filehandler locked the access to the file a new file was getting created. So I created a Synchronized class to handle all logging. And it worked great.
public class SynchronizedLogger {
//Logger to put error logs and messages in the log file
public static Logger logger = Logger.getLogger("MyLog");
//Logger Filehandler
private static FileHandler loggerFH;
public SynchronizedLogger() {
}
public static synchronized void writeLog(String message) {
logger.info(message);
}
public SynchronizedLogger(int i) {
try {
synchronized (this) {
// This block configures the logger with handler and formatter
loggerFH = new FileHandler(System.getProperty("user.dir") + "\\resources\\logs\\logs.txt", 0, 1, true);
logger.setUseParentHandlers(false);
logger.addHandler(loggerFH);
SimpleFormatter formatter = new SimpleFormatter();
loggerFH.setFormatter(formatter);
}
} catch (IOException | SecurityException ex) {
writeLog(ex.getMessage());
outputArea.append("\n\n" + ex.getMessage());
}
}
}
I want to make multiple logging files (For each day), the code I have is this:
public class LoggingInkrement {
static final Logger logger = Logger.getLogger(LoggingInkrement.class.getName());
public static void main(String[] args) {
LogManager manager = LogManager.getLogManager();
try {
FileHandler fhandler = new FileHandler("C:/Users/Administrator/Desktop/Logging%g.txt", 1024*1024,10, true);
SimpleFormatter sformatter = new SimpleFormatter();
fhandler.setFormatter(sformatter);
logger.addHandler(fhandler);
} catch (IOException | SecurityException ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
try {
((Object) null).toString();
}
catch ( Exception e ) {
logger.log( Level.SEVERE, "oh oh", e );
}
logger.info( "Hat funktioniert" );
}
}
my problem is that:
First run: logging0.txt is created
Second run: nothing happens
the changes are unnoticed (it stays on "Hat funktioniert") regardless of the changes i made in logger.info
but my desired outcome is:
You can make logging files with a set size
the files append and dont overwrite till they're full limit
The files are automatically deleted when outdated
logging0.txt
logging1.txt
logging2.txt
and so on
but I have no idea how I could do it
The FileHandler doesn't support daily file rotation. However, you can always trigger a rotation by creating a throw away FileHandler with the limit set to zero and append set to false.
if (isNewDay()) { //then rotate and close.
new FileHandler("C:/Users/Administrator/Desktop/Logging%g.txt",0,5, false).close();
}
//Open the log file.
FileHandler fhandler = new FileHandler("C:/Users/Administrator/Desktop/Logging%g.txt", 1024*1024,10, true);
I have an application that scans a set of files. And this scanning take place parallely. I mean if I upload 5 files, five process will be created and start executing the job parallely. Now For logging the exceptions for the jobs running, there is only one log file. The problem that is coming is, the logger creates a lot of logs files as -
mylogfile.log(actual log file)
mylogfile.log.1
mylogfile.log.2
mylogfile.log.3
mylogfile.log.4
mylogfile.log.5
...
with their respective lock files.
Below is the code snippet that I used:
public static Logger getLogger(final String className) {
final Logger logger = Logger.getLogger(className);
FileHandler fh;
try {
// This block configure the logger with handler and formatter
fh = new FileHandler("mylogfile.log", true);
logger.addHandler(fh);
logger.setLevel(Level.ALL);
logger.setUseParentHandlers(false);
fh.setFormatter(new SimpleFormatter());
} catch (final SecurityException e) {
// }
} catch (final IOException e) {
//
}
return logger;
}
How do I make sure that only one log file should be used to write the exception of all the jobs running parallely..??
Thanks,
Anish
I face the same problem and what I was missing is an standard programming practice that I should close the filehandler after I finish the logging.
So you can create multiple loggers but make sure you close them at the end.
Following 2 lines in below example:
successLogFileHandler.close();
failureLogFileHandler.close();
class LoggerExample {
private Logger loggerFailure;
private Logger loggerSuccess;
public void myLogger() {
// some code block
FileHandler successLogFileHandler = new FileHandler(successLogFile.getAbsolutePath());
FileHandler failureLogFileHandler = new FileHandler(failureLogFile.getAbsolutePath());
// Create loggers
loggerFailure = createLogger(STR_FAILURE_LOG_FILE, failureLogFileHandler, Level.INFO, customFormatter);
loggerSuccess = createLogger(STR_SUCCESS_LOG_FILE, successLogFileHandler, Level.INFO, customFormatter);
// Write messages into loggers
// and at the end close the file handlers
successLogFileHandler.close();
failureLogFileHandler.close();
}
public static Logger createLogger(String strLoggerName, FileHandler handler, Level level, Formatter formatter) throws Exception
{
Logger logger = Logger.getLogger(strLoggerName);
logger.setLevel(level);
handler.setFormatter(formatter);
logger.addHandler(handler);
return logger;
}
}
You can use a singlton locator class that you can retrieve the logger from, that would force your application to use one logger (which means you'll have one log file)
class LoggerLocator {
private static LoggerLocator locator = new LoggerLocator();
private Logger logger;
/**
*
*/
private LoggerLocator() {
initLogger();
}
/**
* #return
*/
public static LoggerLocator getLocator(){
return locator;
}
/**
* #return
*/
public Logger getLogger() {
return logger;
}
/**
*
*/
private void initLogger() {
logger = Logger.getLogger("My General Logger");
FileHandler fh;
try {
// This block configure the logger with handler and formatter
fh = new FileHandler("mylogfile.log", true);
logger.addHandler(fh);
logger.setLevel(Level.ALL);
logger.setUseParentHandlers(false);
fh.setFormatter(new SimpleFormatter());
} catch (final SecurityException e) {
// }
} catch (final IOException e) {
//
}
}
}
In your jobs you will get the logger by the following call:
Logger logger = LoggerLocator.getLocator().getLogger();
This does not have much to do with parallel calls. As well from single thread with each call to your getLogger (even with same string as argument) you create a new FileHandler and add it to existing logger.Maybe you do not want to do all of the setup each time when you call your getLogger-method.
//now we will create new Filehandler and set it to logger
getLogger("identifier").log(Level.SEVERE, "Log to one file");
//now we have already one filehandler, but lets add one more
getLogger("identifier").log(Level.SEVERE, "Log to two files");
//now we have already two filehandlers, but lets add one more
getLogger("identifier").log(Level.SEVERE, "Log to three files");
Configure logging once and after that you can get reference to logger via java.util.loggingLogger.getLogger. Overview from Sun gives more ideas how to configure logging via properties files.