I am extending functionality of a Java project that I inherited that has logging implemented using a class Log that wraps java.util.logging.Logger:
import java.util.logging.*;
public class Log {
// ...
private final Logger log;
I am integrating a third-party library and the problem I've run into is that after I create an object of a class from this library, all logging stops. Or, more precisely, I don't see any log messages in System.err. So in the block below that creates an object of class SomeClass:
public class TopClass {
private static final Log log = new Log(TopClass.class);
// ...
private static SomeClass foo = null;
// ...
public static void main(String[] args) {
// ...
log.severe("SEVERE-BEFORE");
log.info("INFO-BEFORE");
foo = new SomeClass();
log.severe("SEVERE-AFTER");
log.info("INFO-AFTER");
I can see SEVERE-BEFORE and INFO-BEFORE but not SEVERE-AFTER or INFO-AFTER.
How do I figure out what happens with logging during foo's initialization? I have access to some of the source code of the SomeClass library and I searched for any mentions of "log" but did not find any. The library does have a few System.err.priteln() calls. The library also depends on a couple of other libs whose source I don't have access to.
It is possible that the constructor SomeClass of throws an exception.
Try to wrap your code in try-catch.
Something like:
public static void main(String[] args) {
// ...
log.severe("SEVERE-BEFORE");
log.info("INFO-BEFORE");
try
{
foo = new SomeClass();
}
catch (Throwable t)
{
log.severe("an exception was thrown", t);
}
log.severe("SEVERE-AFTER");
log.info("INFO-AFTER");
Related
I'm calling the main method of a class via reflection. For example:
Object o = clasz.getDeclaredConstructor().newInstance();
Method method = clasz.getMethod("main", String[].class);
method.invoke(o, new String[1]);
The called code looks as:
public class Test {
public static void main(String[] args) {
System.out.println("This is a test");
}
}
The reflection works fine and I can see the message in the console.
Is there a way to register something like a binding to the method invocation, for example a PrintWriter or a custom decorated Writer, so I can get the print value as a String?
You can change what System.out is bound to using System.setOut();. You can then make your own:
public class MyTeeingPrinter extends OutputStream {
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
private final PrintStream original;
public MyTeeingPrinter(PrintStream original) {
this.original = original;
}
#Override public void write(int b) {
original.write(b);
buffer.write(b);
}
public String getAndClear() {
String s = buffer.toString(StandardCharsets.UTF_8);
buffer.reset();
return s;
}
}
And then:
MyTeeingPrinter tee = new MyTeeingPrinter();
System.setOut(new PrintStream(tee));
and now you can invoke tee.getAndClear().
It's a bit of a slog, because whatever code you are running like this is presumably badly designed - it should have instead taken a PrintStream or preferrably an Appendable or Writer, and would write into this writer. Then a trivial one-liner main can be made that just tosses System.out into a writer and hands that to this code you're attempting to run for the case where you just want that code to run and write to sysout, and you can make your own (and stop using reflecting to invoke that main method) and hand that to this code you are running in this scenario.
Note that your reflective code 'works' but is bizarre. There is no need to make a new instance; main is static. The right way is:
Method method = clasz.getMethod("main", String[].class);
method.invoke(null, new String[1]);
That main() method is called in the same process, hence, you can just provide your own stdout implementation/decorator via java.lang.System.setOut(PrintStream) before the reflection magic
An empty string array would work: new String[1] -> new String[0]
You don't need to create a new object to call the static method. Even though java allows calling static methods via objects, this is a bad style and sometimes might cause problems because of name shadowing. Consider the example below:
public class Parent {
public static void main(String[] args) {
Parent child = new Child();
child.test();
}
public static void test() {
System.out.println("Parent.test()");
}
}
class Child extends Parent {
public static void test() {
System.out.println("Child.test()");
}
}
It actually calls Parent.test() even though it's invoked on a Child object
To use logger with Java, for now I'm using code like this:
Logger logger = Logger.getLogger("MyLog");
FileHandler fh;
try {
// This block configure the logger with handler and formatter
fh = new FileHandler("c:\\MyLogFile.log", true);
logger.addHandler(fh);
logger.setLevel(Level.ALL);
SimpleFormatter formatter = new SimpleFormatter();
fh.setFormatter(formatter);
// the following statement is used to log any messages
logger.log(Level.WARNING,"My first log");
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
But it always disturbs me somewhat to add this for every class file:
Logger l = Logger.getLogger("MyLog");
How could I refactor out this duplication?
Is there a better recommended way for logging, which could be less intrusive/less repeative but offers the same or even better functions?
You could make l a private static or private field of the class, but apart from that there is no significant improvement.
(There are some bad ideas, like a public static "global" variable, or a private static declaration in a "universal" base class. But those are BAD IDEAS ... not better ways.)
But, hey, one line of code to declare your local logger object is hardly "intrusive" ... is it?
Logging in every class file is a right way, alougth it is looks a little redundancy.
The important function for logging is that record exception. If we want to directly find where occurs the exception, we should know the class name and the method name.
But you maybe be forget to logging when catch exception.
We're using reflection and static fields and this API: http://commons.forgerock.org/bom/apidocs/org/forgerock/i18n/slf4j/LocalizedLogger.html#getLoggerForThisClass()
You could use project lombok to do this:
project lombok is here
The following is the example from their webpage should it ever not be available. To be clear it still generates the statements in your resulting bytecode, but it stops the bolierplate, now you'll have a smaller statement to but in, its horses for courses but the project team I currently work on like it.
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
#Log
public class LogExample {
public static void main(String... args) {
log.error("Something's wrong here");
}
}
#Slf4j
public class LogExampleOther {
public static void main(String... args) {
log.error("Something else is wrong here");
}
}
#CommonsLog(topic="CounterLog")
public class LogExampleCategory {
public static void main(String... args) {
log.error("Calling the 'CounterLog' with a message");
}
}
Vanilla Java
public class LogExample {
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
public static void main(String... args) {
log.error("Something's wrong here");
}
}
public class LogExampleOther {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class);
public static void main(String... args) {
log.error("Something else is wrong here");
}
}
public class LogExampleCategory {
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("CounterLog");
public static void main(String... args) {
log.error("Calling the 'CounterLog' with a message");
}
}
I have a singleton class
public class SingletonText {
private static final CompositeText text = new CompositeText(new TextReader("text/text.txt").readFile());
public SingletonText() {}
public static CompositeText getInstance() {
return text;
}}
And TextReader constructor that could throw FileNameEception
public TextReader(String filename) throws FileNameException{
if(!filename.matches("[A-Za-z0-9]*\\.txt"))
throw new FileNameException("Wrong file name!");
file = new File(filename);
}
How can I rethrow it to main and catch it there?
Main class
public class TextRunner {
public static void main(String[] args) {
// write your code here
SingletonText.getInstance().parse();
System.out.println("Parsed text:\n");
SingletonText.getInstance().print();
System.out.println("\n\n(Var8)Task1:");
SortWords.sortWords(SingletonText.getInstance().getText().toString(), "^[AEIOUaeiou].*", new FirstLetterComparator());
System.out.println("\n\n(Var9)Task2:");
SortWords.sortWords(SingletonText.getInstance().getText().toString(), "^[A-Za-z].*", new LetterColComparator());
System.out.println("\n\n(Var16)Task3:");
String result = SubStringReplace.replace(SingletonText.getInstance()
.searchSentence(".*IfElseDemo.*"), 3, "EPAM");
System.out.println(result);
}}
Static block is executed only when class is loaded for the first time, so you can have something as below which will allow you to re-throw the exception. In you main method, you will surround getInstance() invocation in a try-catch block and then in catch you can do whatever you are looking for.
In case of exception, this exception will be thrown and re-thrown (from you static block) only once, at time of class loading. What #Alexander Pogrebnyak has said is also true.
Looking at the code you have provided, since you are always reading text/text.txt files so below approach will work. In case you are looking to read different files and then re-throwing exception then that becomes all together a different story, and you hadn't asked that part neither the code you have provided shows the same. In any case, if that's what you are looking for then:
you need to create a singleton object of your CompositeText class.
create a setter method will create an object TextReader class using the file name string passed.
that setter method will have the try-catch block, and in the catch block you will re-throw the exception so that you can catch again in main method.
P.S.: since static blocks are executed only once when class is loaded and class is loaded only once per JVM (until you have custom class loaders and overriding the behavior) so this ensures that this singleton is thread-safe.
Code:
public class SingletonText {
private static CompositeText text = null;
static{
try {
text = new CompositeText(new TextReader("text/text.txt").readFile());
} catch (FileNameException e) {
// TODO: re-throw whatever you want
}
}
public SingletonText() {}
public static CompositeText getInstance() {
return text;
}
}
try to lazy initialze the singleton.
something like this:
public class SingletonText {
private static CompositeText text;
public SingletonText() {
}
public static CompositeText getInstance() {
if (text ==null) {
text = new CompositeText(new TextReader("text/text.txt").readFile());
}
return text;
}
}
Also, you need to declare the constructor private, and if it multi-threaded application you need to synchronized the new statement with double check locking. see this in wiki:
https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
Enjoy..
You will get java.lang.ExceptionInInitializerError when your singleton static initializer will fail.
As a cause it will have your FileNameException.
If you don't do anything, default exception handler will print the whole stack trace to standard error.
I never really thought about this before but looking at the following code
public class SomeJavaProgram {
private static String runMe() {
throw new RuntimeException("hi tadsfasdf");
}
private static String name = runMe();
public static void main(String[] args) {
System.out.println("hi there.");
}
}
I never did statics like this in a main before but then I entered scala, and if you have subclasses that start adding defs, exceptions can be thrown before main is even called.
So, in java(not scala), is there a way to catch these exceptions(if I am the superclass and subclasses end up having a static field that throws an exception or static initializer block)....how can I catch all these?
I of course do rely on ONE single definition not throwing which is the
private Logger log = createLoggerFromSomeLoggingLib();
But after that, ideally I would want all exceptions to be logged to the logged file rather than stderr.
That said, I am glad I have always kept the stderr/stdout files along with my logging files now.
Use the static initializer:
private static String name;
static {
try {
name = runMe();
} catch (RuntimeException e) {
// handle
}
}
I have code like below sample. in that I am telling the class_name to get package name. instead of this method, i need another logic to get the package name withoud telling the class_name directly.
package smk.jsf.bean;
public class test {
public static void main(String[] args) {
System.out.println(test.class.getPackage().getName());
//Is there any option like "this.class.getPackage().getName();" bz. i don't want use class_name direclty
}
}
Output : smk.jsf.bean
Thanks to everyone.
Finally I got solution below
package smk.jsf.bean;
public class test {
public static void main(String[] args) {
String className = new Object(){}.getClass().getPackage().getName();
System.out.println(className);
}
Not sure it will suit you but try sun.reflect.Reflection.getCallerClass(). This class is present in JDK.
It will return a Class instance of method caller. Then just getPackage(). It is really dangerous stuff but it lets you not to use the class name directly.
Example usage - create a method String getPackageName() which will get caller class and return package name and call it from main.
Or you can throw any throwable, catch it and parse that throwable's stack trace to get the target package name (really sick way).
I have two approaches.
You can add a field public static final PACKAGE_INFO = "%package%"; to each file. Then traverse your source directory, read the line with the package package someName and replace the %package%
Use a dynamic approach at runtime. I wrote a little example program.
public class PackageExample {
public static void main(String[] args) throws ClassNotFoundException {
Example e = new Example();
System.out.println(e.getPackage());
}
}
interface MetaInformation {
public String getPackage() throws ClassNotFoundException;
}
class InformationGatherer implements MetaInformation {
public String getPackage() throws ClassNotFoundException {
StackTraceElement[] ste = new Exception().getStackTrace();
if (ste.length < 2)
throw new IllegalStateException("StackTrace to small to determine package!");
String clazz = ste[1].getClassName();
Class<?> c = Class.forName(clazz);
String package_ = "";
Package p = c.getPackage();
if (p != null)
package_ = c.getPackage().getName();
return package_;
}
}
class Example implements MetaInformation {
private InformationGatherer ig = new InformationGatherer();
public String getPackage() throws ClassNotFoundException {
return ig.getPackage();
}
}
Not sure if this helps but you can use reflection
http://docs.oracle.com/javase/tutorial/reflect/
Similar question :
See Can you find all classes in a package using reflection?
If it's a static method.No.
You cannot use this in a static context,since main is static method.
If it is not a static method,
String name = this.getClass().getPackage().getName();