Debug mode in a library - java

I have an Android application with several "Log.d" calls along the code in order to following the events of the app.
In order to enable or disable the debug messages I call the Log with
if (MyApp.debug) Log.d("Doing something");
Where MyApp.debug is a final boolean that I change before compiling.
Now I want to use some classes from the application as a library for another app, so I copied them into a new library project. The problem is that now in the library I have no a MyApp class.
How can I make something similar for controlling from the app if the library must print the debug messages or not?
Thanks in advance

I'd suggest placing the variable inside a static class called Log, which you could then, at runtime, have checking a static boolean variable to figure out if it should log or not.
That way, you still have the convenience, but it's all contained inside the logger.
For example:
public class Log {
public static boolean mustLog = false;
// methods etc.
}
Then, in your app, just use if(Log.mustLog) ...
Hope that helps.

You can create a different custom class in your library
public Class LogPrefs
{
public static final boolean enabled = true;
}
and set it on and off as you need. Then just
if (LogPrefs.enabled) Log.d("Doing something");
I always erase debug messages as I go, since they tend to clutter the screen. I keep however Info and Error messages; eventually they can be recovered and sent back after a crash.

Related

Getting the name of class from which a method is being called for logging in Java

I am using log4j for logging purpose in Java. When I use log.info(some message),it logs the api from which the function is being called along with the message,which is what it does.
But my case scenario here is different which I am explaining through code snippets.
ClassA{
void log(String message){
log.info(message);
}
}
ClassB{
classA obj = new classA();
obj.log("hello");
}
In this case while logging log4j will log classA in the log file. But I want it to show classB instead of A. Is it possible achieve this??
You can use one more parameter which contains the name of the class from where you called.
e.g.
ClassA{
void log(String message, String className){
// Edit the log4j details
log.info(message);
}
}
ClassB{
classA obj = new classA();
obj.log("hello", this.getClass().getSimpleName()); //here
}
what you can do is while creating the constructor of log4j pass the name of the class that you want to be in log and rest you can do usually.
Well, wrapping a Logger object inside a custom class like that seems pretty unnecessary, and ... as you are seeing ... it introduces this problem that you wouldn't normally have.
However, it may be possible to make it work. Internally, the log4j formatting code is creating an Exception object to capture the current stack trace, and then trawling that to identify the calling class, method and source file / line. What you could do is to modify the behavior (ideally by overriding things in a custom class) so that it uses the next stack frame up the stack from the one it would normally use.
Unfortunately, relevant log4j code is all heavily abstracted, and rather hard to follow. It would take a few hours for me to figure out the best way to make the necessary changes, and I don't have the inclination to do that. (As I stated at the outset, what you have done is a bad idea ...)
what I did is defined
private static MyLogger logger = MyLogger.getLogger(GetPlanOptionsForPackage.class)
and then
logger.error("input cannot be null");
this solved my use case

Java - Hide system output when testing

I am not sure if it is possible but if so how do I do it? I have a project which contains another 2 projects as dependencies. The parent project is only used for testing purposes (client server app). When I am testing I have a difficulty reading through my testing output because of the large amount of output the client and the server projects have. I am trying to find a way hide from the console all the output(printf()) of my sub-projects so that I can only see my testing output. Is there a way to do so?
For testing I am using JUnit.
Thanks
You should use Java Logger API (or Log4J) instead of using System.out.print directly, sou you could disable specific loggers during executions of your tests.
If you can't change legacy code to use Logger API, there are two options:
Option 1:
Create a PrintStream decorator class like this pseudo-code:
public class FilteredPrintStream extends PrintStream {
private final PrintStream stream;
...
#Override
public void print(String str) {
if (notCalledBySubproject()) {
stream.print(str);
}
}
// override other methods too
}
Then you set default output: System.setOut(new FilteredPrintStream(System.out));
To find method caller (to create notCalledBySubproject method), see How do I find the caller of a method using stacktrace or reflection?
Option 2:
Use Logger API in your test code, so you can redirect your output to a file, for example, then you ignore console output and see the file generated by your tests.
It is not a perfect solution nor good coding practice but you could add a class like this
public class SystemOutput
{
public static final boolean DO_PRINT = true;
public void printf(String format, Object... args)
{
if(DO_PRINT)
System.printf(format, args);
}
}
and use Find and Replace once to replace "System.out.printf" with "SystemOutput.printf" in every class needed. Because both methods have the same declaraction only this has to be changed. When you want to block the output you can just set DO_PRINT to false.
Eclipse for example provides a search tool which can find and replace a certain string in every .java file in a project. (Strg + H under the File Search tab)
of course it is also possible to call System.setOut() with your own subclass of PrintStream, that overrides the printf() method to only print when a certain boolean value is true.
why do you need console to run unit tests? ignore it. if your tests passes you got 0 status code or green bar (IDE or jenkins). any error stack trace you can find in e.g. maven log tests results. just ignore the std output
another thing: using console in your application is usually bad idea - avoid it. use logging framework instead (it will let you control the destination and level of logging). use your IDE and refactor - replace all calls to printf with log.debug or with you own wrapper. if your IDE doesnt support it then use some regex and try replace-all
if you want to get rid of all the output you can redirect stdout to /dev/null or change output stream in java. but it's not a proper solution

Eclipse e4: Accessing properties in PostContextCreate

I am using the PostContextCreate part of the life cycle in an e4 RCP application to create the back-end "business logic" part of my application. I then inject it into the context using an IEclipseContext. I now have a requirement to persist some business logic configuration options between executions of my application. I have some questions:
It looks like properties (e.g. accessible from MContext) would be really useful here, a straightforward Map<String,String> sounds ideal for my simple requirements, but how can I get them in PostContextCreate?
Will my properties persist if my application is being run with clearPersistedState set to true? (I'm guessing not).
If I turn clearPersistedState off then will it try and persist the other stuff that I injected into the context?
Or am I going about this all wrong? Any suggestions would be welcome. I may just give up and read/write my own properties file.
I think the Map returned by MApplicationElement.getPersistedState() is intended to be used for persistent data. This will be cleared by -clearPersistedState.
The PostContextCreate method of the life cycle is run quite early in the startup and not everything is available at this point. So you might have to wait for the app startup complete event (UIEvents.UILifeCycle.APP_STARTUP_COMPLETE) before accessing the persisted state data.
You can always use the traditional Platform.getStateLocation(bundle) to get a location in the workspace .metadata to store arbitrary data. This is not touched by clearPersistedState.
Update:
To subscribe to the app startup complete:
#PostContextCreate
public void postContextCreate(IEventBroker eventBroker)
{
eventBroker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE, new AppStartupCompleteEventHandler());
}
private static final class AppStartupCompleteEventHandler implements EventHandler
{
#Override
public void handleEvent(final Event event)
{
... your code here
}
}

Generic classes in my application

I've created a few minor apps for Android while learning. Being a PHP developer, it's a challenge to get used to it.
I'm especially wondering how I could define a couple of "general" functions in a separate class. Eg I have a function that checks if network connection is available, and if not, shows a dialog saying that the user should enable it. Currently, that function exists in several of my activities. Of course that seems strange - I suppose it would be more logical to define it once and include it in the activites where needed.
I tried putting it in a new class, and included that class in the original activity. But that failed since eg getBaseContext() is not accepted anymore.
I'm wondering how to go ahead. What should I be Google-ing for ? What is this mechanism called?
You need to create class with static methods. Like this
public class HelperUtils {
public static void checkNetworkConnection(Context ctx) {...}
}
Then you can call it from any place like this:
HelperUtils.checkNetworkConnection(this.getContext());
Assuming current class has Context.
You should read books on general OOP concepts where different type of methods are explained.
You can for example create a class - let's call it NetworkUtils. In this class you can create static method boolean isNetworkConnectionAvailable() and return true if is available and false otherwise. In this class you can create another static method void showNoConnectionDialog(Activity activity) - and in this method you create dialog starting with
public static void showNoConnectionDialog(Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
//setting message, listener etc. and finally
builder.create().show();
}
In your activity, where you want to check and handle network connection you should call:
if (!NetworkUtils.isConnectionAvailable(getApplicationContext())) {
NetworkUtils.showNoConnectionDialog(YourActivityClassName.this)
}
I guess this should work.

Accessing a logger in a Java application

I have a question regarding logging in a Java application. I want to log the main user actions and possible errors with user friendly messages. Therefore, I have two appenders for the logger: one shows errors (level = error) in dialogs and the other writes the logs of the current user session into an html-file so that the user could send this file back if something goes wrong.
To avoid having the logger creation in every class (private Logger logger = …) I have a static reference of the configured logger in a class App which has also the methods for accessing the logger:
public class App {
private static Logger logger = Logger.getLogger("logger name");
…
public static void logError(String message, Throwable cause) {
…
}
public static void logInfo(String message) {
…
}
}
The logging is mainly done in the UI classes:
class UIWidget extends UIFrameworkWidget {
void aMethod() {
try {
someBusinessLogic();
} catch (Exception e) {
App.logError(“log message”, e);
}
}
}
Is this a good practice? (Note that the widgets are created by the framework.)
Thanks in advance for answers, comments, or hints on this
Better would be to use a single static Logger instance but allow each class to create a private instance which is initialized with the name of the class (and maybe other info). This private instance then uses the static instance to actually perform its logging but can be omitted if necessary and reduces references to external classes.
This is how slf4j does it, which is a logging framework you should consider using - however you could roll your own in the same manner.
Note, however I don't know how to get your error messages to be displayed within a dialog box - that may need to be explicitly added.
It seems you're just one step away of subclassing the JDK Logger. Having only one static instance prevents you from targeting specific classes at runtime. If you subclass the Logger, then you can still have has many loggers as logged classes and yet keep your appender's peculiarities.
You can also craft your own layout (and, in log4j at least, even add placeholders - geronimo has an example of this).

Categories

Resources