Using OutputStream with multiple ObjectOutputStreams? - java

To abstract from a specific serialization format I thought to define the following:
public interface TransportCodec {
void write(OutputStream out, Object obj) throws IOException;
Object read(InputStream in) throws IOException;
}
A default implementation would use just Java object serialization like this:
public void write(OutputStream out, Object obj) throws IOException {
ObjectOutputStream oout = new ObjectOutputStream(out);
oout.writeObject(obj);
oout.flush();
}
Obviously the oout.close() is missing, but for a reason: I want to be able write several objects into the same stream with independent calls to write. Looking at the source code of ObjectOutputStream (jdk 1.8), oout.close() closes the underlying stream, but also clears data structures that are part of ObjectOutputStream. But since I leave oout right to the garbage collector, I would not expect problems from not closing the stream.
Apart from the risk that a future JDK really needs the oout.close(), two questions:
What do I loose in the current JDK when not closing the ObjectOutputStream above.
First serializing into a ByteArrayOutputStream and then copying the bytes to out would allow to close oout. Are there better options?

Separate into two interfaces and make the implementation class "own" the underlying stream.
Advantages:
Underlying storage is no longer restricted to be an OutputStream / InputStream.
By making the two interfaces extend Closeable, they can now be used in a try-with-resources block.
Caller only need to carry one reference (e.g. TransportEncoder), and will no longer have to carry the stream too (e.g. OutputStream).
Interfaces
public interface TransportEncoder extends Closeable {
void write(Object obj) throws IOException;
}
public interface TransportDecoder extends Closeable {
Object read() throws IOException;
}
ObjectStream implementations
public final class ObjectStreamEncoder implements TransportEncoder {
private final ObjectOutputStream stream;
public ObjectStreamEncoder(OutputStream out) throws IOException {
this.stream = new ObjectOutputStream(out);
}
#Override
public void write(Object obj) throws IOException {
this.stream.writeObject(obj);
}
#Override
public void close() throws IOException {
this.stream.close();
}
}
public final class ObjectStreamDecoder implements TransportDecoder {
private final ObjectInputStream stream;
public ObjectStreamDecoder(InputStream in) throws IOException {
this.stream = new ObjectInputStream(in);
}
#Override
public Object read() throws IOException {
try {
return this.stream.readObject();
} catch (ClassNotFoundException e) {
throw new NoClassDefFoundError(e.getMessage());
}
}
#Override
public void close() throws IOException {
this.stream.close();
}
}

Related

Is it okay to place PrintWriters in java List or Collection?

I am trying to create a server using Sockets, and I am trying to find a way to add multiple sockets to the server by using some sort of array/list/collection.
At the moment I am trying a CopyOnWriteArrayList, but with my not-great knowledge about how Lists and PrintWriters work, I don't think that using a List is what I want to do.
This in my main class is what raises my question:
protected CopyOnWriteArrayList<ClientConnection> clients;
Which forces me to have to close the class as follows:
#Override
public void close() throws IOException {
for (int n = 0; n < clients.size(); ++n) {
// Gets the client
ClientConnection toClose = clients.get(n);
// Closes it
toClose.close();
// Sets the array to be closed.
clients.set(n, toClose);
}
}
Here is the contents of ClientConnection.java:
public class ClientConnection implements java.io.Closeable {
public Socket socket;
public PrintWriter out;
public InputStreamReader in;
public ClientConnection (Socket socket) throws IOException {
this.socket = socket;
out = new PrintWriter(socket.getOutputStream(), true);
in = new InputStreamReader(socket.getInputStream());
}
#Override
public void close () throws IOException {
out.close();
in.close();
socket.close();
}
}
What I want to know is if due to cloning with working with lists, is it bad practice to use lists with PrintWriters and other java.io classes? If so, what is a good alternative?
Your code is totally fine, you can use lists with PrintWriters and java.io in general

Netty TCP Socket InputStream

Netty TCP Server is running at port 8000 receiving NMEA format data. It uses Marine API library to convert the gibberish to a meaningful information which needs input stream from the socket.
SentenceReader sentenceReader = new SentenceReader(socket.getInputStream());
sentenceReader.addSentenceListener(new MultiSentenceListener());
sentenceReader.start();
How can i get inputstream for netty server port being used?
SentenceReader does not have any method to accept "streamed in" data, however with subclassing, it can be made to accept the data.
The core of SentenceReader uses a DataReader for its data, normally this datareader is polled from a seperate thread SentenceReader itself, and we can modify this structure to get what we need.
First, we subclass SentenceReader with our own class, give it the proper constructor and methods we want, and remove the effect of the start and stop methods. We provide null as the file for now (and hope future versions provide a method to pass a datareader in directly)
public class NettySentenceReader extends SentenceReader {
public NettySentenceReader () {
super((InputStream)null);
}
#Override
public void start() {
}
#Override
public void stop() {
}
}
We now need to implement all functionality of the internal class DataReader inside our own Netty handler, to replicate the same behaviour
public class SentenceReaderHandler extends
SimpleChannelInboundHandler<String> {
private SentenceFactory factory;
private SentenceReader parent;
public SentenceReaderHandler (SentenceReader parent) {
this.parent = parent;
}
#Override
public void channelRegistered(ChannelHandlerContext ctx) {
if(!ctx.channel().isActive())
return;
//ActivityMonitor monitor = new ActivityMonitor(parent);
this.factory = SentenceFactory.getInstance();
}
#Override
public void channelActive(ChannelHandlerContext ctx) {
//ActivityMonitor monitor = new ActivityMonitor(parent);
this.factory = SentenceFactory.getInstance();
}
#Override
// This method will be renamed to `messageReceived` in Netty 5.0.0
protected void channelRead0(ChannelHandlerContext ctx, String data)
throws Exception {
if (SentenceValidator.isValid(data)) {
monitor.refresh();
Sentence s = factory.createParser(data);
parent.fireSentenceEvent(s);
} else if (!SentenceValidator.isSentence(data)) {
parent.fireDataEvent(data);
}
}
#Override
public void channelInactive(ChannelHandlerContext ctx) {
//monitor.reset();
parent.fireReadingStopped();
}
#Override
public void channelUnregistered(ChannelHandlerContext ctx) {
if(!ctx.channel().isActive())
return;
//monitor.reset();
parent.fireReadingStopped();
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) {
parent.handleException("Data read failed", e);
}
}
Finally, we need to integrate this into a Netty pipeline:
SentenceReader reader = new NettySentenceReader();
bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
private static final StringDecoder DECODER = new StringDecoder();
#Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast(DECODER);
pipeline.addLast(new SentenceReaderHandler(reader));
}
});
You can't easily as InputStream is blocking and netty is an async - non blocking API.

What is the recommended way close IO resources declared as instance variables

In some of the Java classes I see the IO resources declared as instance varibles and are being used in multiple methods.How can I close them?Few Suggested finalize() and they also say that it is not recommended. May I know if there is any better approach for this.?
Ex:
public class test{
private PrintWriter writer=null;
public test(){
createWriter();
}
public void log(){
writer.write("test");
writer.flush();
}
public void createWriter(){
writer=new PrintWriter(new BufferedWriter(new FileWriter("file")));
}
}
Implements AutoCloseable in your class and override close() method and close all your IO related resources in this close() method.
Now if you are using Java 7 you can create a reference to your class using try with resource and JVM will automatically call close method of your class.
As you can see in the code of FilterReader class,
public abstract class FilterReader extends Reader {
protected Reader in;
//......Other code, and then
public void close() throws IOException {
in.close();
}
}
And if you write
try(FileReader fr = new FileReader("filename")){
// your code
}
and you are done JVM will automatically close it
There shoud be some kind of destructor. In junit for example (as you are naming your class "test") you have #AfterClass annotation to do your clean-up in such annotated method.
You just close it manually after you use it.
public class PrintWriterDemo {
private PrintWriter writer;
public PrintWriterDemo() {
writer = new PrintWriter(System.out);
}
public void log(String msg) {
writer.write(msg + "\n");
writer.flush();
}
public void close() {
System.out.println("print writer closed.");
writer.close();
}
public static void main(String[] args) {
PrintWriterDemo demo = new PrintWriterDemo();
demo.log("hello world");
demo.close();
}
}

How to cleanly deal with "unreported exception IOException" in stream/forEach?

I'm trying to write to a file using Java Streams. To my knowledge you don't have to catch an exception as long as you throw it forward.
The compiler however throws an error (on the line of the stream.foreach()...) and says
error: unreported exception IOException; must be caught or declared to be thrown
Could someone explain why this is?
(I'm only interested in solutions using streams)
public void save(String file, ArrayList<String> text) throws IOException {
FileWriter fw = new FileWriter(file);
text.stream().forEach(x->fw.write(x +"\n"));
fw.close();
}
Netbeans suggests this, but is there a shorter way?
public void save(String file, ArrayList<String> text) throws IOException {
FileWriter fw = new FileWriter(file);
text.stream().forEach(x->{
try {
fw.write(x +"\n");
} catch (IOException ex) {
...
}
});
fw.close();
}
Unfortunately there's no easy solution to this. Lambda expressions that throw checked exceptions need to be caught. Probably the neatest way to do this is to convert the checked exception to an unchecked exception in a separate method.
try {
text.forEach(this::write);
catch (UncheckedIOException ex) {
...
}
private void write(String line) throws UncheckedIOException {
try {
fw.write(line +"\n");
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
});
Though, to be honest, this is not really any neater than NetBean's suggestion other than making your save method cleaner.
If you are unclear on the checked/unchecked exception distinction then read the accepted answer here.
Note that List has a forEach method (actually Iterable that List extends) so stream() is redundant.
The forEach action expects a Consumer whose accept method does not allow to throw checked exceptions. In your case, the solution is simple:
public void save(String file, ArrayList<String> text) throws IOException {
Files.write(Paths.get(file), text, Charset.defaultCharset());
}
If it really has to be a stream operation, you could use
public void save(String file, ArrayList<String> text) throws IOException {
Files.write(Paths.get(file),
(Iterable<String>)()->text.stream().iterator(), Charset.defaultCharset());
}
writing it this way works as the stream operation does not throw checked exceptions, instead, the outer operation Files.write may.
A general solution for dealing with checked exceptions in a Consumer could be a helper method performing the wrapping and unwrapping:
interface IOConsumer<T> extends Consumer<T> {
public default void accept(T t) {
try { doIO(t); } catch(IOException ex) { throw new UncheckedIOException(ex); }
}
void doIO(T t) throws IOException;
public static <E> void doForEach(Stream<? extends E> s, IOConsumer<? super E> c)
throws IOException {
try{ s.forEachOrdered(c); } catch(UncheckedIOException ex){ throw ex.getCause(); }
}
}
which you can use like
public void save(String file, ArrayList<String> text) throws IOException {
try( FileWriter fw = new FileWriter(file) ) {
IOConsumer.doForEach(text.stream(), x -> fw.write(x +"\n"));
}
}
This construct ensures that you properly handle potential IOExceptions at the initiator level. Note that I replaced your unsafe explicit close() call with the proper try-with-resource construct.
With this, you still can use arbitrary intermediate stream operations, i.e. doForEach(text.stream().intermediateOp1().iOp2(), x -> fw.write(x +"\n")) or stream sources other than collections.

How to handle a variable being used by 2 threads?

One thread keeps reading bytes received from a BufferedReader. The data comes from a SerialPort.
On the main thread, there is a JMenuItem when it's clicked the serial port is closed and the BufferedReader should stop receiving the messages.
The problem is:
If I try to close while messages are being read, the application will stuck and the serial port won't be closed until the port stops sending messages.
So basically, I should close the reader before closing the serial port. If I do this, sometimes I get a null pointer exception because I close the buffered reader while he is being read.
How can I solve this issue?
It sounds like you can fix this with a stop method in your reader class (called from the menu item's click event)
private boolean isStopped = false;
public void stop() {
isStopped = true;
}
while(bufferedReader.isReady()) {
bufferedReader.read();
if(isStopped) {
bufferedReader.close();
}
}
This way you ensure that you don't call close until all read calls have completed.
The simplest thing to do would be to create a SynchronizedReader class which would wrap your BufferedReader. But without more context, I cannot guarantee this will work, especially if you have calling code which makes multiple interdependent calls to the Reader (you would then need to ensure that all calls are made in a single synchronized(reader) block).
import java.io.IOException;
import java.io.Reader;
import java.nio.CharBuffer;
public class SynchronizedReader extends Reader {
private Reader reader;
public SynchronizedReader(Reader reader) {
super();
this.reader = reader;
}
#Override
public synchronized int read(char[] cbuf, int off, int len) throws IOException {
return reader.read(cbuf, off, len);
}
#Override
public synchronized void close() throws IOException {
reader.close();
}
#Override
public synchronized int hashCode() {
return reader.hashCode();
}
#Override
public synchronized int read(CharBuffer target) throws IOException {
return reader.read(target);
}
#Override
public synchronized int read() throws IOException {
return reader.read();
}
#Override
public synchronized int read(char[] cbuf) throws IOException {
return reader.read(cbuf);
}
#Override
public synchronized boolean equals(Object obj) {
return reader.equals(obj);
}
#Override
public synchronized long skip(long n) throws IOException {
return reader.skip(n);
}
#Override
public synchronized boolean ready() throws IOException {
return reader.ready();
}
#Override
public synchronized boolean markSupported() {
return reader.markSupported();
}
#Override
public synchronized void mark(int readAheadLimit) throws IOException {
reader.mark(readAheadLimit);
}
#Override
public synchronized void reset() throws IOException {
reader.reset();
}
#Override
public synchronized String toString() {
return reader.toString();
}
}

Categories