I am struggling with the following problem and ask for help.
My application has a logger module. This takes the trace level and the message (as string).
Often should be messages constructed from different sources and/or different ways (e.G. once using String.format in prior of logging, other times using .toString methods of different objects etc). Therefore: the construction method of the error messages cannot be generalized.
What I want is, to make my logger module effective. That means: the trace messages would only then be constructed if the actual trace level gets the message. And this by preventing copy-paste code in my application.
With C/C++, by using macros it was very easy to achive:
#define LOG_IT(level, message) if(level>=App.actLevel_) LOG_MSG(message);
The LOG_MSG and the string construction was done only if the trace level enabled that message.
With Java, I don't find any similar possibility for that. That to prevent: the logging would be one line (no if-else copy-pastes everywhere), and the string construction (expensive operation) only be done if necessary.
The only solution I know, is to surrond every logger-calls with an IF-statement. But this is exactly what I avoided previously in the C++ app, and what I want to avoid in my actual Java-implementation.
My problem is, on the target system only Java 1.6 is available. Therefore the Supplier is not a choice.
What can I do in Java? How can this C/C++ method easily be done?
Firstly, I would encourage you to read this if you're thinking about implementing your own logger.
Then, I'd encourage you to look at a well-established logging API such as SLF4j. Whilst it is possible to create your own, using a pre-existing API will save you time, effort and above all else provide you with more features and flexibility out of the box (I.e file based configuration, customisability (look at Mapped Diagnostic Context)).
To your specific question, there isn't a simple way to do what you're trying to do. C/C++ are fundamentally different to java in that the preprocessor allows for macros like you've created above. Java doesn't really have an easy-to-use equivalent, though there are examples of projects that do make use of compile time code generation which is probably the closest equivalent (i.e. Project Lombok, Mapstruct).
The simplest way I know of to avoid expensive string building operations whilst logging is to surround the building of the string with a simple conditional:
if ( logger.isTraceEnabled() )
{
// Really expensive operation here
}
Or, if you're using Java 8, the standard logging library takes a java.util.function.Supplier<T> argument which will only be executed if the current log level matches that of the logging method being called:
log.fine(()-> "Value is: " + getValue());
There is also currently a ticket open for SLF4j to implement this functionality here.
If you're really really set on implementing your own logger, the two above features are easy enough to implement yourself, but again I'd encourage you not to.
Edit: Aspectj compile time weaving can be used to achieve something similar to what you're trying to achieve. It would allow you to wrap all your logging statements with a conditional statement in order to remove the boilerplate checking.
Newest logging libraryies, including java.util.logging, have a second form of methods, taking a Supplier<String>.
e.g. log.info( ()->"Hello"); instead of log.info("Hello");.
The get() method of the supplier is only called if the message has effectively to be logged, therefore your string is only constructed in that case.
I think the most important thing to understand here is that the C/C++ macro solution, does not save computational effort by not constructing the logged message, in case the log level was such that the message would not be logged.
Why is so? Simply because the macro method would make the pre-processor substitute every usage of the macro:
LOG_IT(level, message)
with the code:
if(level>=App.actLevel_) LOG_MSG(message);
Substituting anything you passed as level and anything you passed as message along with the macro itself. The resulting code to be compiled will be exactly the same as if you copied and pasted the macro code everywhere in your program. The only thing macros help you with, is to avoid the actual copying and pasting, and to make the code more readable and maintainable.
Sometimes they manage to do it, other times they make the code more cryptic and thus harder to maintain as a result. In any case, macros do not provide deferred execution to save you from actually constructing the string, as Java8 Logger class does by using lambda expressions. Java defers the execution of the body of a lambda until the last possible time. In other words, the body of the lambda is executed after the if statement.
To go back to your example in C\C++, you as a developer, would probably want the code to work regardless of the log level, so you would be forced to construct a valid string message and pass it to the macro. Otherwise in certain log levels, the program would crash! So, since the message string construction code must be before the call to the macro, you will execute it every time, regardless of the log level.
So, to make the equivalent to your code is quite simple in Java 6! You just use the built-in class: Logger. This class provides support for logging levels automatically, so you do not need to create a custom implementation of them.
If what you are asking is how to implement deferred execution without lambdas, though, I do not think it is possible.
If you wanted to make real deferred execution in C\C++ you would have to make the logging code such, as to take a function pointer to a function returning the message string, you would make your code execute the function passed to you by the function pointer inside the if statement and then you would call your macro passing not a string but a function that creates and returns the string! I believe the actual C\C++ code to do this is out of scope for this question... The key concept here, is that C\C++ provide you the tools to make deferred execution, simply because they support function pointers. Java does not support function pointers, until Java8.
I want to do something which seems really straightforward: just pass a lot of logging commands (maybe all, but particularly WARN and ERROR levels) through a method in a simple utility class. I want to do this in particular so that during testing I can suppress the actual output to logging by mocking the method which does this call.
But I can't find out how, with ch.qos.logback.classic.Logger, to call a single method with the Level as a parameter ... obviously I could use a switch command based on this value, but in some logging frameworks there's a method or two which lets you pass the logging Level as a parameter. Seems a bit "primitive" not to provide this.
The method might look a bit like this:
Logger.log( Level level, String msg )
Later
Having now looked up the "XY problem" I understand the scepticism about this question. Dynamic logging is considered bad, at least in Java (possibly less so in Python)... now I know and understand that the preferred route is to configure the logging configuration appropriately for testing.
One minor point, though, if I may: although I haven't implemented this yet with this particular project, I generally find "just" tracing the stacktrace back to the beginning of the particular Thread insufficient, and this is what logback does (with Exceptions passed at WARN or ERROR levels). I plan to implement a system for recording "snapshots" of Threads when they run new Threads... which can then be listed (right back to the start of the app's first Thread) if an error occurs. This is, if you like, another justification for using something to "handle" outgoing log calls. I suppose that if I want to implement something like this I will instead have to try to extend some elements of logback in some way.
I have some importand methods in code that are used in a wrong way, people don't get the whole context of the process and invokes wrong methods, for example setters. If I had something like #Deprecated it could highlight / strike/ underline methods and show som info when somebody uses it. For example someone set some variables that are even not persisted as he thought that it would persist. Another person changed one method and spoiled dozen of usecases becaouse he didnt know about them..
I use Java7 and IntelliJ Idea 14
Instead of using an annotation, program defensively, check if the parameters you get make sense. Write tests to verify what happens when invalid input is provided.
I think Automated Tests, Good Method Names and such will do more good than some fancy IDE plugin to stop other developers from invoking wrong methods.
I'm using a number of frameworks, boot, hibernate, etc, in our code, including enhancing and generating code. When I call what looks like a simple method of code it will go through CglibAoPProxy and similar methods before to call the method I want. This means if I want to look into the next piece of my code I need to either walk through 5 lays of stack trace for code I presume is functional (and thus don't care to trace it's logic) to get to the next method of code I personally wrote, or add breakpoints and where I want to break, hit run, and then remove the breakpoint after.
What would be nice is if there was an easy way to tell the debugger that I only want to look at my code. If I step into a method implemented by some library just keep running until it hits the next line of code that is part of a library I wrote. Is there an easy way to configure the debugger to do this? to only care about code I personally wrote when stepping into something?
Likewise, when I want to move back up the stack trace, to look at an earlier phase state, it's very difficult. With so many levels of methods from libraries it's hard to find the ones that contain code I personally wrote. Is there a way to highlight only your methods (say methods from the current working set) or something similar in the stack trace?
Step filters may help.
Open Eclipse preferences. For example, on Windows, use the menu item Windows>Preferences.
Navigate to Java>Debug>Step Filtering.
Turn on the checkbox Use Step Filtering.
In the checkbox list titled Defined step filters, turn on checkboxes of package hierarchies you'd like to skip. Use the buttons alongside to add additional filters.
All that said, I hadn't used step filtering until your question led me to look into it. Not yet sure how I personally feel about skipping code while debugging. But that last item in the default filter list -- java.lang.ClassLoader -- looks very helpful.
There is a Java application and I have no permission to alter the Java code apart from annotating classes or methods (with custom or existing annotations).
Using annotations and annotations only I have to invoke code which means that every time an instance of an annotated class is created or an annotated method is called, some extra Java code must be executed (e.g a call to a REST Webservice). So my question is: how can I do this?
In order to prevent answers that I have already checked I will give you some solutions that seem to work but are not satisfying enough.
Aspect Oriented Programming (e.g AspectJ) can do this (execute code before and after the call of an annotated method) but I don't really want the runtime overhead.
Use the solution provided here which actually uses reflection. This is exactly what I need only that it alters the initial code further than just annotating and so I cannot use it.
Use annotation processor for source code generation as suggested here by the last answer. However, still this means that I will alter the source code which I don't want.
What I would really like is a way to simply include a Java file that somehow will execute some Java lines every time the annotated element will be triggered.
Why not skip annotations completely and use byteman to inject code at runtime into the entry points of your code.
I have to agree with the comment above though, that this sort of restriction is ridiculous and should be challenged.