Read response before send it - java

I am sending a plain text file to the user through a servlet.
I am using flatworm framework to build the flat file. I receive the file in the browser but is empty. So i want start the debugging analysing the outputstream before being sent.
How i can read the response before i send it in the servlet? I think is the same thing that asking how can i transform an OutputStream to an InputStream.
I already saw solutions that always involve ByteArrayOutputStream , and as you know when i call in the servlet response.getOutputStream() it returns me an OutputStream and not a ByteArrayOutputStream.

There seems to be some confusion somewhere, though I'm not sure exactly where.
What can you do with an OutputStream? Why, you can write to it, and that's about it. That means that if you're given (or look up) an output stream, it's up to you to supply the data - which means you already have it.
Perhaps on the other hand, you're not directly calling write on the OutputStream yourself, but passing this stream into the flatworm library (which will in turn write output to it). In that case, there's your debugging "hook" right there - flatworm will write out the file to any output stream you send it. So in this case, instead of passing in the servlet's stream, you pass in a stream that you've created yourself.
That might be a ByteArrayOutputStream, which (after the flatworm method has returned) you can inspect to get the bytes written. At this point you could manually write them through to the response's output stream. Or maybe you need to do something slightly trickier and create your own stream wrapper which writes straight through to the underlying response stream but logs on the way - and pass this into flatworm.
The bottom line however is that if you're interacting with an output stream, then "your" code already has the data somewhere locally and it's just a matter of capturing/accessing that.

Related

Entering data into an InputStream

I know that InputStreams are for reading, and OutputStreams are for writing... but if I have an application that passes all data from an InputStream to the remote side and pushes all received data from that remote side to the OutputStream and I need to send dynamic data to that remote side... how would I enter it into the InputStream? I can do this easily in the Java console since anything entered in is put into System.in and sent to that remote side, and anything coming back is processed through System.out, but obviously I cannot use a Java console in production. How would I emulate this functionality e.g. create a button that sends "command X\r" as if it were typed into the java console?
Note: For background, I'm using JSch to SSH into a Cisco ASA. Where I have set Channel.setInputStream(System.in) and Channel.setOutputStream(System.out) to communicate through console successfully.
I am not familiar with JSch, and I suspect you have this backwards. First, according to their example, you should actually be executing commands with Channel.setCommand(). Then you can use Channel.getInputStream() to obtain a stream that you can read the remote response from.
That aside, a cursory glance at the documentation seems to suggest that you should use the channel's existing streams and read to / write from them, e.g.:
OutputStream out = Channel.getOutputStream();
String str = "command X\r";
out.write(str.getBytes("us-ascii"));
This would make more sense and is much easier to deal with on your end.
However, as to the general question regarding InputStreams: You can use any InputStream as a source for data. It just so happens that System.in is one that comes from standard input (which is essentially a file).
If you want to use data constructed on the fly, you could use a ByteArrayInputStream, e.g.:
String str = "command X\r";
InputStream in = new ByteArrayInputStream(str.getBytes("us-ascii"));
// do stuff with in
You can use any character encoding you want if us-ascii is not appropriate.
But, again, I suspect you are doing this slightly backwards.

Custom Buffered Input Stream for on-the-fly reading/pull

I need to pass an InputStream to an object which reads data which I previously stored into a File. I'm assessing a more efficient approach than storing eveything into a File and then passing the FileInputStream. I'd like to do it on the fly.
May someone appoint me the correct approach to do that?
The idea would be passing a Custom InputStream which innerly calls every line I was going to store in the file. I guess I need buffering. I discard storing everything in a String and then build an InputStream on it, as we are in the same situation, waiting to output all the lines before rereading them again.
There already is a stream for this. It's the PipedInputStream. You'll need to have one thread write to the PipedOutputStream, and pass the PipedInputStream to the object that will be reading in another thread.

Java using streams as sort of "buffers"

I'm working with a library that I have to provide an InputStream and a PrintStream. It uses the InputStream to gather data for processing and the PrintStream to provide results. I'm stuck using this library and its API cannot be altered.
There are two issues with this that I think have related solutions.
First, the data that needs to be read via the InputStream is not available upfront. Instead, the data is dynamically created by a different part of the application and given to my code as a String via method call. My code's job is to somehow allow the library to read this data through the InputStream provided as I get it.
Second, I need to somehow get the result that is written to the PrintStream and send it to another part of the application as a String. This needs to happen as immediately after the data is put in to the PrintStream as possible.
What it looks like I need are two stream objects that behave more or less like buffers. I need an InputStream that I can shove data in to whenever I have it and a PrintStream that I can grab it's contents whenever it has some. This seems a little awkward to me, but I'm not sure how else to do it.
I'm wondering if anything already exists that allows this kind of behavior or if there is a different (better) solution that will work in the situation I've described. The only thing I can come up with is to try to implement streams with this behavior, but that can become complicated fast (especially since the InputStream needs to block until data is available).
Any ideas?
Edit: To be clear, I'm not writing the library. I'm writing code that is supposed to provide the library with an InputStream to read data from and a PrintStream to write data to.
Looks like both streams need to be constantly reading/writing so you'll need two threads independent of each other. The pattern resembles JMS a little bit, in which case you're feeding information to a "queue" or "topic", and wait for it to be processed then put on a "output" queue/topic. This may introduce additional moving parts, but you could write a simple client to place info onto a JMS queue, then have a listener to just grab messages, and feed it to the input stream constantly. Then another piece of code to read from output stream, and do what you need with it.
Hope this helps.

How to write multiple objects to file?

I want to write multiple objects to a file, but the problem is that I dont have all the objects to write at once. I have to write one object and then close the file, and then maybe after sometime I want to add another object to the same file.
I am currently doing it as
FileOutputStream("filename", true)
so that it will append the object to the end of file and not overwrite it. But I get this error :
java.io.StreamCorruptedException: invalid type code: AC
any ideas how can I solve this issue ?
Thanks,
One option is to segment the file into individual messages. When you want to write a message, first serialize it to a ByteArrayOutputStream. Then open the file for appending with DataOutputStream - write the length with writeInt, then write the data.
When you're reading from the stream, you'd open it with DataInputStream, then repeatedly call readInt to find the length of the next message, then readFully to read the message itself. Put the message into ByteArrayInputStream and then deserialize from that.
Alternatively, use a nicer serialization format than the built-in Java serialization - I'm a fan of Protocol Buffers but there are lots of alternatives available. The built-in serialization is too brittle for my liking.
You can't append different ObjectOutputStreams to the same file. You would have to use a different form of serialization, or read the file in and write out all the objects plus the new objects to a new file.
You need to serialize/deserialize the List<T>. Take a look at this stackoverflow thread.

How to create a file that streams to http response

I'm writing a web application and want the user to be able click a link and get a file download.
I have an interface is in a third party library that I can't alter:
writeFancyData(File file, Data data);
Is there an easy way that I can create a file object that I can pass to this method that when written to will stream to the HTTP response?
Notes:
Obviously I could just write a temporary file and then read it back in and then write it the output stream of the http response. However what I'm looking for is a way to avoid the file system IO. Ideally by creating a fake file that when written to will instead write to the output stream of the http response.
e.g.
writeFancyData(new OutputStreamBackedFile(response.getOutputStream()), data);
I need to use the writeFancyData method as it writes a file in a very specific format that I can't reproduce.
Assuming writeFancyData is a black box, it's not possible. As a thought experiment, consider an implementation of writeFancyData that did something like this:
public void writeFancyData(File file, Data data){
File localFile = new File(file.getPath());
...
// process data from file
...
}
Given the only thing you can return from any extended version of File is the path name, you're just not going to be able to get the data you want into that method. If the signature included some sort of stream, you would be in a lot better position, but since all you can pass in is a File, this can't be done.
In practice the implementation is probably one of the FileInputStream or FileReader classes that use the File object really just for the name and then call out to native methods to get a file descriptor and handle the actual i/o.
As dlawrence writes the API it is impossible to determine what the API is doing with the File.
A non-java approach is to create a named pipe. You could establish a reader for the pipe in your program, create a File on that path and pass it to API.
Before doing anything so fancy, I would recommend analyzing performance and verify that disk i/o is indeed a bottleneck.
Given that API, the best you can do is to give it the File for a file in a RAM disk filesystem.
And lodge a bug / defect report against the API asking for an overload that takes a Writer or OutputStream argument.

Categories