How to tie a PrintStream to the System.out and err streams - java

I'm trying to tie my PrintStream object to the console's output and error streams so that whatever I write there will also be written to my log file.
public static void tieOutputStreams(String fileName) {
try {
File output = new File(fileName);
FileWriter writer = new FileWriter(output);
writer.close();
outputStream = new TiedOutputStream(output);
}
catch (Exception e) {
e.printStackTrace();
}
System.setErr(outputStream);
System.setOut(outputStream);
}
Once I'm done writing, I could reset it back to the way things were.
public static void resetOutputStreams() {
outputStream.close();
System.setErr(System.err);
System.setOut(System.out);
}
TiedOutputStream class looks like this:
public class TiedOutputStream extends PrintStream {
public TiedOutputStream(File logFile) throws FileNotFoundException {
super(logFile);
}
#Override
public void print(Object obj) {
super.print(obj);
System.out.print(obj);
}
#Override
public PrintStream printf(String format, Object... args) {
super.printf(format, args);
System.out.printf(format, args);
return this;
}
#Override
public void println(Object args) {
super.println(args);
System.out.println(args);
}
}
And my main method:
public static void main(String[] args) {
try {
TieOutputStreams.tieOutputStreams("./sample.log");
System.out.println("Output console");
System.err.println("Error console");
float num = 1.123456f;
System.out.printf("A float: %.6f", num);
} catch (Exception e) {
e.printStackTrace();
}
finally {
TieOutputStreams.resetOutputStreams();
}
}
I want these statements to be printed on both my log file and the System consoles (out / err). For reasons I don't know, this isn't working. I appreciate all the answers and comments. Thanks in advance!
I know there is Log4j. But I want to do this anyway.

This doesn't work mainly because you didn't save the original System.out and because you didn't override println(String obj) When you call System.out.println("Output console"); you won't hit in the method you override because that one expects and object and there is a more specific method in PrintStream that expects a String argument
This seems to work:
public class TiedOutputStream extends PrintStream {
private final PrintStream sout;
private final PrintStream serr;
public TiedOutputStream(File logFile) throws FileNotFoundException {
super(logFile);
sout = System.out;//save standard output
serr = System.err;
}
#Override
public void print(Object obj) {
super.print(obj);
sout.print(obj);
}
#Override
public void println(String obj) {
super.println(obj);
sout.println(obj);
}
#Override
public PrintStream printf(String format, Object... args) {
super.printf(format, args);
sout.printf(format, args);
return this;
}
#Override
public void println(Object args) {
super.println(args);
sout.println(args);
}
}
Not sure why tieOutputStreams created that FileWriter
public static void tieOutputStreams(String fileName) {
try {
File output = new File(fileName);
outputStream = new TiedOutputStream(output);
System.setErr(outputStream);
System.setOut(outputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
main method remains the same. You should update resetOutputStreams to restore to original out and err. I would override all print* method from PrintStream if I would use this.

Related

Mockito to test the catch block of private method

I need to write a test to verify that when an IOException is thrown by the private method_C, Method_B returns True.
But
public final class A{
public static Boolean Method_B(){
try{
//call a private method C which throws IOException
Method_C
}
catch(final IOException e) {
return Boolean.True
}
}
private static Method_C() throws IOException {
return something;
}
What I tried:
#Test
public void testSomeExceptionOccured() throws IOException {
A Amock = mock(A.class);
doThrow(IOException.class).when(Amock.Method_C(any(),any(),any(),any()));
Boolean x = A.Method_B(some_inputs);
Assert.assertEquals(Boolean.TRUE, x);
}
I am getting compilation errors :
1.Cannot mock a final class
2. Method_C has private access in A
Any suggestions on how this can be rectified?
you are required to use finally in try catch
import java.io.*;
public class Test {
public static Boolean Method_B() {
try {
System.out.println("Main working going..");
File file = new File("./nofile.txt");
FileInputStream fis = new FileInputStream(file);
} catch (IOException e) {
// Exceptiona handling
System.out.println("No file found ");
} catch (Exception e) {
// Exceptiona handling
System.out.println(e);
} finally {
return true;
}
}
public static void main(String args[]) {
if (Test.Method_B()) {
System.out.println("Show true ans");
} else {
System.out.println("Sorry error occure");
}
}
}

calling method on other java application via lan

i have 2 java applications connected to each other via LAN (wifi network)
the first one ServerApp.java
public class ServerApp {
public static void zzz(){
System.out.println("hi");
}
public static void main(String[] args) {
try {
ServerSocket ss=new ServerSocket(6666);
Socket s=ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
String str =(String)dis.readUTF();
System.out.print("message : "+str);
ss.close();
} catch (IOException e) {
System.out.println(e);
}
}
}
the second one ClientApp.java
public class ClientApp {
public static void main(String[] args) {
try {
Scanner in = new Scanner(System.in);
System.out.print("send message to the server ?[y/n]:");
String inputString=in.next();
if ("y".equals(inputString)) {
Socket s= new Socket("192.168.20.125", 6666);
DataOutputStream dout=new DataOutputStream(s.getOutputStream());
dout.writeUTF("hellow server\n");
dout.writeUTF("zzz");
dout.flush();
dout.close();
s.close();
} else if ("n".equals(inputString)) {
System.out.println("exit");
} else {
System.out.println("error: you should enter a valid value");
}
} catch (IOException e) {
System.out.println(e);
}
}
}
what happens is, the client app send a message to the server app via LAN using the server IP address - the server app have a method call zzz() so all I want is how do I make the client app call this method ( if possible )
thanks
#MichalLonski how to I make the "obj" indicate to the ServerApp
As it is static method you have to point ServerApp.class, like below:
public class ServerApp {
public static void zzz() {
System.out.println("hi");
}
public static void main(String[] args) throws Exception {
String methodName = "zzz";
java.lang.reflect.Method method = ServerApp.class.getMethod(methodName);
method.invoke(ServerApp.class);
}
}
You can change it to use not static, but instance methods. In order to do that you have to create an instance of ServerApp class, like this:
public class ServerApp {
public void foo() {
System.out.println("Hello there from non static method!");
}
public static void main(String[] args) throws Exception {
String methodName = "foo";
ServerApp app = new ServerApp();
java.lang.reflect.Method method = app.getClass().getMethod(methodName);
method.invoke(app);
}
}
Edit:
If you want to specify also the class of which method you want to call, you can do it this way:
package com.example;
class Foo {
public static void bar() {
System.out.println("Hello there.");
}
}
public class ServerApp {
public static void main(String[] args) throws Exception {
//read the class and method name from the socket
String className = "com.example.Foo";
String methodName = "bar";
Class<?> clazz = Class.forName(className);
clazz.getMethod(methodName).invoke(clazz);
}
}

Mock FileInputStream using Mockito/PowerMockito without having an existing file

I am writing a JUnit for a method that uses FileInputStream and in the constructor only the file name is passed. The file is created as part of a servlet request and this file is not stored any where.
I am trying to Mock FileInputStream using PowerMockito so that it gives me a mocked file object. Unfortunately I get FileNotFoundException which is valid but I am not sure how to test this method then because the file doesn't exist.
Method under test:
public String viewReport() throws Exception {
this.inputStream = new FileInputStream(DOCUSIGN_REPORT_FILE);
try {
boolean returnReport = validateRequest();
if (returnReport) {
intgList = this.generateViewIntegrationReportData(getESignUIConfig());
this.createCSVFile(intgList, new FileWriter(DOCUSIGN_REPORT_FILE));
} else {
failureResponse(msgs, 400);
return null;
}
} catch (Exception e) {
e.printStackTrace();
msgs.add(new Message(ESignatureIntegrationMessageTypeEnum.MESSAGE_TYPE_ERROR,
UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_CODE_500, UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_TEXT_SERVICE_ERROR));
failureResponse(msgs, 500);
return null;
}
return UiIntegrationKeyConstants.REPORT_REPSONSE;
}
JUnit test so far.
#Test
public void testViewReport() throws Exception {
Map<String, Object> actionMap = new HashMap<>();
actionMap.put("application", "ESignatureIntegrationAction");
ActionContext.setContext(new ActionContext(actionMap));
FileInputStream inputStream = Mockito.mock(FileInputStream.class);
PowerMockito.whenNew(FileInputStream.class).withAnyArguments().thenReturn(inputStream);
action = new ESignatureIntegrationAction();
action.viewReport();
}
I get an exception when the code reaches to new FileInputStream(DOCUSIGN_REPORT_FILE);
Thanks for the help.
I would suggest to refactor your code in a way that allows testing without a mocking framework.
It could look somewhat like this:
public class YourClass {
// ...
public String viewReport() {
try {
boolean isValidRequest = validateRequest();
if (isValidRequest) {
IntegrationReportCsvFileHandler fileHandler = new IntegrationReportCsvFileHandler();
IntegrationReportData inputData = fileHandler.readData(new FileInputStream(DOCUSIGN_REPORT_FILE));
IntegrationReportGenerator generator = new IntegrationReportGenerator();
IntegrationReportData outputData = generator.processData(inputData, getESignUIConfig());
fileHandler.writeReport(outputData, new FileWriter(DOCUSIGN_REPORT_FILE));
} else {
failureResponse(msgs, 400);
return UiIntegrationKeyConstants.FAILURE_RESPONSE;
}
} catch (Exception e) {
e.printStackTrace();
msgs.add(new Message(ESignatureIntegrationMessageTypeEnum.MESSAGE_TYPE_ERROR,
UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_CODE_500, UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_TEXT_SERVICE_ERROR));
failureResponse(msgs, 500);
return UiIntegrationKeyConstants.FAILURE_RESPONSE;
}
return UiIntegrationKeyConstants.REPORT_RESPONSE;
}
// ...
}
public class IntegrationReportData {
// your custom data structure
// may as well just be a List<Data>
// may be different for input and output
}
public class IntegrationReportException extends Exception {
// your custom exception
public IntegrationReportException(String message) { super(exception); }
}
public class IntegrationReportGenerator {
public IntegrationReportData processData(IntegrationReportData data, ESignConfig config) throws IntegrationReportException {
// here's your logic that requires testing
}
}
public class IntegrationReportCsvFileHandler {
public IntegrationReportData readData(InputStream input) throws IOException {
// read data from given input stream
}
public void writeData(IntegrationReportData data, OutputStreamWriter outputWriter) throws IOException {
// write data to given output stream
}
}
That way the IntegrationReportGenerator would be easily testable.

Dot Tool BinarySearchTree Java

I simply try to write to a dot file following addition of integers to a BinarySearchTree, but no file is generated to the project file upon execution.
public void testadd()
{
BinarySearchTree<Integer> bst = new BinarySearchTree<Integer>();
bst.add(1);
bst.add(2);
bst.add(3);
bst.add(4);
bst.add(5);
bst.writeDot("BST.dot");
}
public static PrintStream out;
public void writeToFile( ) throws IOException{
out = new PrintStream(new FileOutputStream("BST.dot"));
writeToFile(root);
out.close();
}
public void writeToFile(BinaryTreeNode t) throws IOException
{
if (t != null)
{
System.setOut(out);
System.out.println(t.info);
writeToFile(t.left);
writeToFile(t.right);
}
}

Java - Capturing System.err.println or Capturing a PrintStream

Java Newbie question :
I need to capture the text being written to a printStream by a 3rd party component.
The PrintStream is defaulted to System.err, but can be changed to another PrintStream.
Looking through the docs, I couldn't find an easy way to direct the contents of a PrintStream to a string writer / buffer.
Can someone please assist?
PipedOutputStream pipeOut = new PipedOutputStream();
PipedInputStream pipeIn = new PipedInputStream(pipeOut);
System.setOut(new PrintStream(pipeOut));
// now read from pipeIn
import java.io.*;
public class Test {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("errors.txt");
} catch(IOException ioe) {
System.err.println("redirection not possible: "+ioe);
System.exit(-1);
}
PrintStream ps = new PrintStream(fos);
System.setErr(ps);
System.err.println("goes into file");
}
}
You can create a PrintStream around any other OutputStream.
The simplest way to create one that goes to a buffer in memory would be:
PrintStream p = new PrintStream( new ByteArrayOutputStream() )
Then you could read and reset the contents of the byte array at whatever points you like.
Another possibility would be to use pipes.
InputStream third_party_output = new PipedInputStream();
PrintStream p = new PrintStream( new PipedOutputStream( third_party_output ) );
Then you could read from the third_party_output stream to get the text written by the library.
Are you looking for something like this?
OutputStream redirect = System.err;
PrintStream myPrintStream = new PrintStream(redirect);
myPrintStream.println("hello redirect");
If you can pass myPrintStream to the 3rd party application, you can redirect it anywhere you want.
I use the following class to log System.out and System.err to a set of rotating files (where xxx-001.log is the most recent). It contains a few call to utility methods, which you will need to implement before it will compile - they should be self-explanatory.
import java.io.*;
import java.lang.reflect.*;
public class LoggerOutputStream
extends OutputStream
{
// *****************************************************************************
// INSTANCE PROPERTIES
// *****************************************************************************
private FileOutputStream log=null; // the base output stream
private String fnmBase,fnmExt; // filename base, file extension
private int fnmCount,fnmLast; // count for filename index, last filename used
private int logSize,totWritten; // max log size, current number of bytes written
// *****************************************************************************
// INSTANCE CONSTRUCTORS/INIT/CLOSE/FINALIZE
// *****************************************************************************
public LoggerOutputStream(String baseFilename) throws IOException {
this(baseFilename,".log",2,1024000);
}
public LoggerOutputStream(String baseFilename, String extension) throws IOException {
this(baseFilename,extension,2,1024000);
}
public LoggerOutputStream(String baseFilename, String extension, int numberOfFiles, int maxFileSize) throws IOException {
fnmBase=baseFilename;
if(Character.isLetterOrDigit(fnmBase.charAt(fnmBase.length()-1))) { fnmBase=(fnmBase+"-"); }
fnmExt=extension;
if(!fnmExt.startsWith(".")) { fnmExt=('.'+fnmExt); }
fnmCount=numberOfFiles;
logSize=maxFileSize;
if(fnmCount>MAXLOGS) { fnmCount=MAXLOGS; }
fnmLast=0;
for(int xa=1; xa<=MAXLOGS; xa++) {
if(!new File(constructFilename(xa)).exists()) {
while((--xa)>fnmCount) { IoUtil.deleteFile(constructFilename(xa)); }
fnmLast=xa;
break;
}
}
log=null;
openFile(false);
if(numberOfFiles>MAXLOGS) { System.out.println("** Log File Count Limited To "+MAXLOGS); }
}
public void close() throws IOException {
close(false);
}
private void openFile(boolean ovrflw) throws IOException {
close(true);
if (fnmLast< fnmCount) { fnmLast++; }
else if(fnmLast==fnmCount) { IoUtil.deleteFile(constructFilename(fnmCount)); }
for(int xa=fnmLast; xa>0; xa--) { IoUtil.renameFile(constructFilename(xa-1),constructFilename(xa)); }
log=new FileOutputStream(constructFilename(1));
totWritten=0;
}
private String constructFilename(int index) {
return constructFilename(fnmBase,index,fnmExt);
}
private synchronized void close(boolean ovrflw) throws IOException {
if(log!=null) {
log.flush();
log.close();
log=null;
}
}
// *****************************************************************************
// INSTANCE METHODS - ACCESSORS
// *****************************************************************************
public String getFilename() {
return constructFilename(1);
}
public String getFilename(int idx) {
return constructFilename(idx);
}
public synchronized void cycleLogFile() throws IOException {
openFile(true);
}
// *****************************************************************************
// INSTANCE METHODS
// *****************************************************************************
public synchronized void flush() throws IOException {
if(log!=null) {
log.flush();
}
}
public synchronized void write(int val) throws IOException {
if(log!=null) {
log.write(val);
totWritten++;
if(val=='\n') {
if(totWritten>logSize) { openFile(true); }
else { log.flush(); }
}
}
}
public synchronized void write(byte[] bytes) throws IOException {
if(log!=null) {
log.write(bytes);
totWritten+=bytes.length;
if(bytes.length>0 && bytes[bytes.length-1]=='\n') {
if(totWritten>logSize) { openFile(true); }
else { log.flush(); }
}
}
}
public synchronized void write(byte[] bytes, int str, int len) throws IOException {
if(log!=null) {
log.write(bytes,str,len);
totWritten+=len;
if(bytes.length>(str+len-1) && bytes[str+len-1]=='\n') {
if(totWritten>logSize) { openFile(true); }
else { log.flush(); }
}
}
}
// *****************************************************************************
// STATIC PROPERTIES
// *****************************************************************************
static public final int MAXLOGS=999; // maximum log files allowed
// *****************************************************************************
// STATIC METHODS
// *****************************************************************************
static public String constructFilename(String bas, int idx, String ext) {
if(!bas.endsWith("-") && !bas.endsWith("_") && !bas.endsWith(".")) { bas=(bas+"-"); }
if(!ext.startsWith(".") ) { ext=('.'+ext); }
return (bas+TextUtil.raZeros(idx,3)+ext);
}
} /* END PUBLIC CLASS */

Categories