Redirecting Java System Out to JavaFX

Having an issue where Logger doesn’t use system out for output stream

Free Starter Code, MIT License

package testing;

import java.util.logging.Logger;

import color.AsciiColorUtil;

public class TestLogger {
	private Logger logger;
	
	public TestLogger(final Logger logger) {
		this.logger=logger;
	}
	
	public void logSuccess() {		
		System.out.println(AsciiColorUtil.GREEN+"Test completed successfully"+AsciiColorUtil.DEFAULT);
	}
	
	public void logSuccess(String message) {
		System.out.println(AsciiColorUtil.GREEN+message+AsciiColorUtil.DEFAULT);
	}
	
	public void info(String message) {
		System.out.println(message);
	}
	
	public void severe(String message) {
		System.err.println(message);
	}
	
	public void logFailure(String message) {
		System.err.println(AsciiColorUtil.RED+message+AsciiColorUtil.DEFAULT);
	}
}

The solution doesn’t feel right, but the right solution wastes time.

package application.controller;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.HashMap;

import graphicsView.components.ViewComponentUtil;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
import math.AdditionUtilTest;
import multithreading.ThreadUtil;

public class AppController {
	Application application;
	Scene scene;
	Stage primaryStage;
	int width;
	int height;
	
	Parent root;
	HashMap<String, Node> idMap;
	
	public Parent getRoot() {
		return root;
	}

	public void setRoot(Parent root) {
		this.root = root;
		idMap=ViewComponentUtil.getIdNodeMap(root);
	}	
	
	public int getWidth() {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	public Application getApplication() {
		return application;
	}

	public void setApplication(Application application) {
		this.application = application;
	}

	public Scene getScene() {
		return scene;
	}

	public void setScene(Scene scene) {
		this.scene = scene;
	}

	public Stage getPrimaryStage() {
		return primaryStage;
	}

	public void setPrimaryStage(Stage primaryStage) {
		this.primaryStage = primaryStage;
	}
	
	TextArea textAreaOutput;
	
	public void launchStartupSequence() {
		scene = new Scene(root,width,height);
		
		LoadCssCommand loadCssComand = new LoadCssCommand(application,scene);
		loadCssComand.run();
		
		primaryStage.setScene(scene);
		primaryStage.show();
		textAreaOutput = (TextArea) idMap.get("textAreaOutputConsole");
		redirectSystemOutToTextArea();
	}
	
	public void redirectSystemOutToTextArea() {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
	    PrintStream ps = new PrintStream(System.out) {
	    	PrintStream baosPrintStream = new PrintStream(baos);
	    	
	    	public void println(String message) {
	    		baosPrintStream.println(message);
	    		super.println(message);
	    	}
	    };
	    System.setOut(ps);
	    
	    PrintStream err = new PrintStream(System.err) {
	    	PrintStream baosPrintStream = new PrintStream(baos);
	    	
	    	public void println(String message) {
	    		baosPrintStream.println(message);
	    		super.println(message);
	    	}
	    };	    
	    System.setErr(err);
	    
	    
	    var object = new Object() { int count = 0; };
	    ThreadUtil.addTask(() -> {
		    while (true) {
		    	object.count++;
		    	if (object.count%30==0) {
		    		System.err.println("Stay Alive Message "+object.count);
		    	}
		    	textAreaOutput.setText(baos.toString());
		    	
		    	try {
		    		Thread.sleep(100);
		    	} catch (InterruptedException e) {
		    		
		    	}
		    }
	    });
	    
	    runTestCases();
	}
	
	public static void runTestCases() {
		AdditionUtilTest additionUtilTest = new AdditionUtilTest();
		additionUtilTest.testSumListOfIntegers();
	}
}

When I call System.out I get the value that I can redirect to a window, when I use logger class for some reason it still sends to system.err yet bypasses System.err, might use another method than println(), tried another method and seemed to be a problem.

Updated to attach directly to Global Logger

	TextArea textAreaOutput;
	
	public void launchStartupSequence() {
		scene = new Scene(root,width,height);
		
		LoadCssCommand loadCssComand = new LoadCssCommand(application,scene);
		loadCssComand.run();
		
		primaryStage.setScene(scene);
		primaryStage.show();
		textAreaOutput = (TextArea) idMap.get("textAreaOutputConsole");
		redirectSystemOutToTextArea();
	}
	
	public void redirectSystemOutToTextArea() {
		Logger.getLogger("").addHandler(new Handler() {
			
			@Override
			public void publish(LogRecord record) {
				// TODO Auto-generated method stub
				textAreaOutput.setText(textAreaOutput.getText()+record.getMessage()+"\n");
			}

			@Override
			public void flush() {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void close() throws SecurityException {
				// TODO Auto-generated method stub
				
			}
		});
	    
	    runTestCases();
	}

Kind of odd if you use “” for Logger it adds handler to Global Logger yet if you add Logger.GLOBAL_LOGGER_NAME instead it does not work.

Published by techinfodebug

Flex and Java Developer, Christian, Art, Music, Video, and Vlogging

Leave a comment