My application has to output content for the user. Throughout all my classes I've just been using System.out.println, but since the program isn't intended to be run by command line this isn't really suitable.
I had thought of simply making a classes that extends JPanel and having all the content append to a textarea. I've been reading that this isn't a good move, and an issue arises in that I'll have to pass the JPanel class to all the classes that output text.
Is there a good-practice alternative to System.out.println? If not, how do you suggest I proceed? I have suggestions of Java Logging, but I don't want to output to a file.
You should have limited user interaction in most of your classes and in fact the UI code should be separate in its own set of class. You should strive to write your model (non-UI) code so that it can work well in a console application, a Swing application, an SWT application or other UI library type application. This way your code can work with SOP or with GUI's as you see fit. I will wager that > 90% of Java classes created by professional coders have no UI code within them.
Also please note that logging and user interaction code are two completely orthogonal concepts. I look at logging as a way to communicate with the developer and supporter, not the user.
Agree with #Hovercraft's comment. Don't pass the JPanel, have a static method in your UI class that all other objects call when they need to output. That method will handle formatting and appending and all that.
Moreover there isn't really an alternative to println when it comes to Java. That's because println only outputs to stdout and in a GUI application it's hidden unless the user executes your program from command line.
What you want is a configurable logging framework, like Log4j. By writing a custom log appender, you have have your log output appear anywhere you want, not just in a file: http://www.javaworld.com/javaworld/jw-12-2004/jw-1220-toolbox.html
The reason is that sending messages to stdout is usually inappropriate in a production environment. If you're coding a library, the library should return information to its caller, not print to stdout. If you're coding a GUI app, the information should be presented to the user, not to where stdout happens to be pointing (which might be nowhere). If you're coding a server (or something that runs in a server-side container) you should be using whatever logging facility the framework has provided. And so forth.
The logger gives to ability to define different levels of importance of the logged messages and the ability to use different sink for the output - the console, a file, etc.
Also it's easy to enable or disable only some type of message when using a logger - for example you don't want to see every debug message in production.
I don't think that using loggers offers any significant advantages in unit tests, but I'd prefer it even there anyways. In unit tests asserts are usually my primary concern.
Btw you should really consider using something like Commons Logging or SLF4J as a log framework facade - it's bad style to tie your code to a specific logging framework. Common Logging and SLF4J make it easy to switch logging frameworks if you choose to.
The best method to output information to your user depends on the kind of app you're working on.
If your app is batch-oriented and highly technical, it might be appropriate to send output to a scrolling text area (JTextArea) so users can view the latest status and scroll back to get details if they want.
But if it's more interactive and less technical in nature, you should try to minimize output to only the most essential things, like high-level status messages, or critical error messages. Simple dialogues (JOptionPane) and status bars (JLabel) might be best in that case.
In either case, if your app is large, you should consider designing it so that you don't scatter a lot of UI code in with everything else. Keeping the main logic separate from the presentation code will help with maintenance later on. One well-accepted approach to doing that is called model-view-controller (MVC).
Here are a couple good links to get you started on MVC.
Wikipedia article on Model-view-controller
Stackoverflow question: The MVC pattern and SWING
Is there a good-practice alternative to System.out.println?
return
Related
I've written a console app in Java, that uses Google Protocol Buffers for serialization.
However, when that code is used, during library loading, it outputs some warnings about illegal reflective access operations.
AFAIK, that's some minor Google annoyance that doesn't really affect anything, so I would like my app not to dump that trash to output.
At the same time, I obviously want my app to output its own stuff as normal.
How does one generally go about things like this?
What would be a good way to handle this concrete situation?
The best way would be to add a logger and not use the standard console output. You can read about slf4j. It has many advantages over the standard output. You can have different levels of the log you want to see - info,debug,warn,error etc. So you can limit the amount of information you read. Also you will keep previous outputs in files and also you can configure different appenders - so different classes write their outputs into different files.
Basically this is the preferred way for most java applications and there is a reason why
The program I'm building seems to freeze at some points on the user's system. When I test the very same steps, I see no problem. Even though Java is supposed to be a platform-independent VM, my guess is it has to do with the systems we're using (I'm on linux, the user on Mac), maybe something with file access.
I cannot access the user's system, and the user has no idea what debugging means. In order to test where the problem is, I was thinking of writing the program's progress to a file, and having him send me the file when there's a problem. Therefore my question:
Is there some kind of library which allows writing the line by line execution of a program to a file? Ideally, the values of certain variables would also be included.
edit: I'm familiar with Logger, but (like one answer says), that would require writing a lot of log statements. Is there some way to do this automatic? Maybe line by line is overkill, but something like log each method entry/exit would definitely work.
Thanks a lot!
This might be a good use case for aspect-oriented programming. Specifically, the AspectJ library for Java might suit your needs (there are others, but this is the one I'm most familiar with). You could define a logging aspect that would automatically insert method entry/exit log messages into the methods you wish to trace, without having to modify the code for those methods. The aspect can be included or excluded as you wish whenever you build the application (eg, include it just for this user until you resolve the issue).
Something like the following might be a good start:
aspect LogAllMethods {
Log log = new Log(); // pseudocode -- replace with whatever logging mechanism you like
before(): call(public * com.mycompany.*.*(..)) {
log.log("Entered method: " + thisJoinPoint);
}
after(): call(public * com.mycomapny.*.*(..)) {
log.log("Leaving method: " + thisJoinPoint);
}
}
This basically says that, before and after any public method call in the package com.mycompany, log the entry/exit and the name of the method (thisJoinPoint is a special variable in AspectJ that refers to the point in the program's execution that the aspect is being applied to). The AspectJ documentation has some nice tutorials and examples of defining aspects and how they can be used, as well as instructions on how to introduce aspects into your application.
This might be overkill for your situation and underutilization of AspectJ, but it should allow you to do some fine-grained debugging without having to add logging calls to every method in your code.
Typically the debug information you want would be included in a log file. Logging frameworks like Java's built in Logging API allow you to configure what severity of messages to produce when the program is run. In other words, you could have it normally report severe errors only, but enable debug output selectively when you need more information.
However, logging frameworks normally require you, the programmer, to explicitly tell it what to log. It doesn't simply log everything (that would be a lot of data too!).
It sounds like what you want is logging in your application. See the Wikipedia article for Java Logging Frameworks for details.
Some of the more common logging frameworks, all mentioned in the aforementioned article, are:
Log4J
Java Logging API
Apache Commons Logging
SLF4J
I want to log information to a file and want to know is there any advantage in using the Java Logger class versus my own personal method of logging?
I know using a logger I just add my own FileHandler to the logger. My personal method is just using a FileOutputStream.
Honestly your logger may be as good, it's pretty easy to put in log levels, filtering, etc.
The problem is when you start to put together code from 10 different groups each with their own logging. Some use System.out, some use some custom logger, some use log4j, ...
How do you parse or redirect the output? How do you filter all that output to just show your messages (For instance, filtering options in log4j won't prevent messages being sent straight to System.out).
It's a pretty big bulk change depending on which system you are moving from/to. Better just to use one very common one from the beginning and hope that it's the one everybody else on the project chooses.
The real question is: why would you bother writing your own logger when there are already existing libraries for doing that? Does your logger do something that the others don't? I kind of doubt it.
Standardization is another big issue - see Bill K's answer.
For most scenarios, a standard logging framework is the way to go. They are pretty flexible. But using your own implementation can also be a valid option, specially if we are not speaking of traditional logging (global debugging, problems, warning messages) but about specific informational meesages or accounting.
Among other factors, bear in mind that the standarization of logging allows third party libraries to cooperate. For example, if you have a standard web application using (say) Hibernate, and you have configured a standard Java logging lib, then you can not only log from your own code but also tell Hibernate to log debugging info to your log files (not necessarily the same files). That is very useful - almost a must.
If you code your own logging library with a plain FileOutputStream, you must decide -among other things- if you are going to keep the file opened, or reopen-append-close in each write - and you must take of synchronization and related issues. Nothing terribly complicated, though.
The logger gives to ability to define different levels of importance of the logged messages and the ability to use different sink for the output - the console, a file, etc.
Also it's easy to enable or disable only some type of message when using a logger - for example you don't want to see every debug message in production.
A logging framework allows you specify logging levels (e.g. log only critical messages, log only debug messages etc.). It also allows you to log to multiple destinations (e.g. to a file, to syslog etc.) and you can do this even after your application is fully built by just changing a config file and not changing any code. It can also format your logs easily depending on various parameters.
There are numerous other advantages since proper logging is a rather involved problem and these packages have been written to solve them. I think the important question, why would you not use them?
Well I would always prefer tested thing and approved by community over something which still need a lot of test. Logger allows you many things which will consume you some time to implement and to test the robustness of your solution. A big plus will be the know-how of the next person who will do something with your code, in case it will be your logger, normally it would take more time to learn how its working out, since there is much more examples and documentation for java.util.logger.
Like all others mention, there are more advantages to using a more common logging system over writing your own. To be honest, the Java util logging api is not nearly as extensive and configurable as other libraries you might find out there on the internet.
Bare in mind that rolling your own always has the disadvantage of being less tested and therefore more prone to break or skip some potentially crucial messages.
Personally I prefer using SLF4J since it allows me to plug in adapters for more commonly used logging frameworks and then let's me pick my own actual logging implementation, this solves most of the problems with different library writers preferring different logging frameworks. And if you consider yourself up for the task you could writer an implementation for SLF4J yourself ;)
Say you have an application with a series of actions. How would you write it such that actions are logged when they are triggered?
Use a Template pattern.
Use AOP.
Use a Listener and Events.
Use a combination of the above.
Something else (explain).
I'd vote for AOP for the sake of eliminating redundancy, but only if there's room for AOP in your project.
You can have custom logging using a logging library from your methods elsewhere in your project, but in a particular component where you hold many similar classes and want to log similar things for all of them, it can be painful to copy/paste and make sure everyone knows how to log.
EDIT: regarding the other enumerated approaches, I think the advantage of AOP would be that it doesn't require you to design your code (template methods or events) specifically for this topic. You usually don't lose any of the code flexibility when spotting cross-cutting concerns and treating them as such, as opposed to redesigning a whole class hierarchy just to make use of consistent logging.
I think the best answer is using log4j (or sli4j, if that's the latest) inside an aspect.
Logging is the "hello world" of AOP. If you aren't using AOP, you're doing it wrong.
It really would depend on your specific context. Specifically on what was being tracked and how the application currently worked. If the actions are classes that all have a common base class and all you care about is the name of the action, then a simple addition to log in this class would be a great choice. If you have actions spread across several layers of code, then an AOP or Listener/Event type solution might work better. If that application was a web app vs desktop or if you ultimately need the logs feed to a database, webservice, or just want text files all make a difference.
if you simply want to log particular actions it's probably simplest to use a logging api such as commons-logging or log4j etc add a log statement in the code you wish to track.
Have you heard of any library which would allow me to set up tracing for specific methods at runtime?
Instead of adding (and removing) lots of System.out.println in my code (and having to re-compile and re-deploy) I would like to have a magic thing which would print out a line for each call of selected method without any change in the code. This would work without re-compiling, so some kind of JVM agent (or some non-standard JVM would be needed?). Sounds like a job for aspect programming?
A typical scenario would be to start an application, configure the traced methods dynamically (in a separate file or similar) and then everytime a selected method is called a line with its name (and arguments) is printed out to System.out (or some log file).
Naturally one could think of tens of additional features, but this basic set would be a great tool. BTW, I use Eclipse interactive debugger too, not only the System.out tracing technique, but both have some advantages and sometimes Eclipse is not enough.
Yes what you are referring to is known as Aspect oriented programming. A typical library providing this for Java is AspectJ. You define what are called pointcuts, essentially regular expressions for classes and method names, including wildcards, and the code to execute at each pointcut, known as an advice. This is useful for logging and also security checks and similar cross cutting concerns.
You can turn pointcut advices on and off through configuration. You can have an advice execute before a method call, after it returns or even after it throws an exception. Arguments are also available.
An aspectj java agent is needed for this to work.
In my experience, that kind of very detailed tracing (much more detailed than one would normally use for logging) as a debugging technique is indicative of insufficient unit testing and integration testing.
You can do this using a tool called InTrace.
NOTE: InTrace is a free and open source tool which I have written.
Log4J useful for disabling logging depending on "log-level" (DEBUG, INFO, WARN, FATAL).
You specify in configuration file what the least level you want to appear in logs, e.g., don't log anything below INFO level, and voila!
Looks like there's yet another solution - called Byteman. In their own words:
Byteman is a tool which simplifies tracing and testing of Java
programs. Byteman allows you to insert extra Java code into your
application, either as it is loaded during JVM startup or even after
it has already started running. The injected code is allowed to access
any of your data and call any application methods, including where
they are private. You can inject code almost anywhere you want and
there is no need to prepare the original source code in advance nor do
you have to recompile, repackage or redeploy your application. In fact
you can remove injected code and reinstall different code while the
application continues to execute.
Jackplay is the tool you are looking for.
It allows you to enable logging on method entry and exit points without any coding or redeployment.
It also allows redefining a method body. It gives you web based UI as control panel to enable or undo tracing on your class.methods.