Scope management - Stateful IO Monad? - java

I am playing with functional programming and in particular with Functional Java. I have implemented with success my version of the IO Monad and I am writing IO actions for my core. It is basically serializing objects to Xml files (the object type extends the custom XmlWritable interface).
Unfortunately, in order to do that, an instance of OutputStream AND one instance of XmlSerializer needs to be created. The scope of the OutputStream is wider than XmlSerializer's, which means that the only way I can see to be able to correctly handle both lifecycles within my IO monad is to carry both of them with me in a tuple, closing OutputStream after having written using XmlSerializer.
This leads to heavy and ugly code (Java 6 is definitely not the best for this):
public abstract class IO<R> {
[...]
}
public class IOActions {
public final F<String, IO<OutputStream>> openFileFn() {
return new F<String, IO<OutputStream>>() {
#Override
public IO<OutputStream> f(String fileName) {
[...]
}
};
}
/* This will be partially applied, encoding will be fixed */
public static final F<OutputStream, IO<P2<OutputStream, XmlSerializer>>> initSerializer() {
return new F<OutputStream, IO<P2<OutputStream, XmlSerializer>>>() {
#Override
public IO<P2<OutputStream, XmlSerializer>> f(OutputStream os) {
XmlSerializer = new ...
[...]
}
};
}
/* This will be partially applied as well */
public static final F2<XmlWritable, P2<OutputStream, XmlSerializer>, IO<P2<OutputStream, XmlSerializer>>> writeObjectFn() {
return new F2<XmlWritable, P2<OutputStream, XmlSerializer>, IO<P2<OutputStream, XmlSerializer>>>() {
#Override
public IO<P2<OutputStream, XmlSerializer>> f(XmlWritable object, P2<OutputStream, XmlSerializer> p) {
[...]
}
};
}
Is there a more idiomatic why to handle my use case in functional programming?
Lurking, I discovered the State Monad...but I am kind of scared to see what it is going to happen if I apply a State Monad on top of a IO Monad in Functional Java.

I actually took great inspiration from Functional-Java's DB combinators to solve similar problems. I made my very own "XML combinators" (and more) from this pattern, so its worth learning.
You might find this discussion on google groups useful.
edit - replying to the comment:
follow the code:
notice how you start a new connection using the StateDb, see that you have a few options to start a connection, one that eventually commits, and one that eventually rollback. these are just two examples of things you can "carry" with the computation. Essentially, every computation that you bind (a plain modaic bind), could potentially carry information.
here is an example i gave in the discussion above:
DB<PreparedStatement> prepareStatement(final String sql) {
return new DB<PreparedStatement>() {
public PreparedStatement run(Connection c) throws SQLException {
return c.prepareStatement(sql);
}}}
// for a query that a reader might perform, i might have a function like this:
F<PreparedStatement, DB<ResultSet>> runStatement() {
public DB<ResultSet> f(final PreparedStatement s) {
return new DB<ResultSet>() {
public ResultSet run (Connection c) throws SQLException {
return s.executeQuery();
}}}
So in this example, you can pass extra information, namely the sql query as a parameter to the function that gets bound. you could just as well had more parameters to runStatement.
to put it all together, you get something like:
ResultSet rs = DbState.reader("conn-url").run(prepareStatement("select * from table").bind(runStatement());
Hope this helps!

Here is what I have come up with. Feedback is very appreciated.
I followed the answer above, taking inspiration from the linked discussion:
public class IOXml<T extends XmlWritable> implements DataWriter<T>{
private final XmlSerializer mXmlSerializer;
private final Option<String> mXmlEncoding;
private final IO<OutputStream> ioCreateStream;
private final F<OutputStream, IO<Unit>> ioCloseStream;
#Inject
IOXml(IO<OutputStream> createStream, F<OutputStream, IO<Unit>> closeStream, XmlSerializer xmlSerializer, Option<String> xmlEncoding) {
mXmlSerializer = xmlSerializer;
mXmlEncoding = xmlEncoding;
ioCreateStream = createStream;
ioCloseStream = closeStream;
}
/**
* Write a T object which is XmlWritable.
* #param osAndSer The tuple containing OutputStream and XmlSerializer.
* #param object The object to write.
* #return IO monad object.
*/
protected IO<Unit> writeObject(final T object) {
return new IO<Unit>() {
#Override
public Unit performIO() throws IOException {
object.writeXml(mXmlSerializer);
return Unit.unit();
}
};
}
protected final F<Unit, IO<Unit>> writeObjectFn(final T object) {
return new F<Unit, IO<Unit>>() {
#Override
public IO<Unit> f(Unit a) {
return writeObject(object);
}
};
}
/**
* Initialize the XmlSerializer before using it.
* #param os An OutputStream.
* #param encoding The encoding of the xml file.
* #return An IO action returning nothing.
*/
protected IO<Unit> initXml(final OutputStream os) {
return new IO<Unit>() {
#Override
public Unit performIO() throws IOException {
mXmlSerializer.setOutput(os, mXmlEncoding.toNull());
mXmlSerializer.startDocument(mXmlEncoding.toNull(), true);
return Unit.unit();
}
};
}
/**
* Close the XmlSerializer after.
* #return An IO action returning nothing.
*/
protected IO<Unit> closeXml() {
return new IO<Unit>() {
#Override
public Unit performIO() throws IOException {
mXmlSerializer.endDocument();
return Unit.unit();
}
};
}
protected final F<Unit, IO<Unit>> closeXmlFn() {
return new F<Unit, IO<Unit>>() {
#Override
public IO<Unit> f(Unit a) {
return closeXml();
}
};
}
#Override
public void close() throws IOException {
closeXml().performIO();
}
#Override
public void write(T object) {
throw new UnsupportedOperationException("Are you sure? IOXml is a functional class. Use the function returned by liftIO instead.");
}
/**
* Curried function to write XML objects, given the object itself and an OutputStream.
* #return The curried function.
*/
protected F<OutputStream, F<T, IO<Unit>>> writeFn() {
// returning the outer
return new F<OutputStream, F<T, IO<Unit>>>() {
#Override
public F<T, IO<Unit>> f(final OutputStream os) {
// Returning the inner
return new F<T, IO<Unit>>() {
#Override
public IO<Unit> f(T object) {
return initXml(os).bind(writeObjectFn(object)).bind(closeXmlFn());
}
};
}
};
}
#Override
public IO<Unit> writeIO(final T object) {
return IOImpl.bracket(ioCreateStream, // init
ioCloseStream, // close
Function.partialApply2(writeFn(), object)); // body
}
}

Related

Abstract Generic Object class

Hi
In the game Minecraft you have to send data between the client and the server in order to sync stuff, one of the things that need to be synced in particular circumstances is TileEntities with a render. The data is stored on the server and sent to the client which is thereafter used for render.
You create a class that contains the data that needs to be synced and attach it to a channel creation API called "SimpleImpl". My Network object and a Message Object:
public class IntercraftPacketHandler
{
private static int index = 1;
private static final ResourceLocation CHANNEL_NAME = new ResourceLocation(Reference.MODID,"network");
private static final String PROTOCOL_VERSION = new ResourceLocation(Reference.MODID,"1").toString();
public static SimpleChannel getNetworkChannel()
{
final SimpleChannel channel = NetworkRegistry.ChannelBuilder.named(CHANNEL_NAME)
.clientAcceptedVersions(version -> true)
.serverAcceptedVersions(version -> true)
.networkProtocolVersion(() -> PROTOCOL_VERSION)
.simpleChannel();
// Sync Capability Identity Hidden data message.
channel.messageBuilder(MessageIdentityHidden.class,index)
.encoder(MessageIdentityHidden::encode)
.decoder(MessageIdentityHidden::decode)
.consumer(MessageIdentityHidden::handle)
.add(); index++;
// Send TreeTapTileEntity data to client.
channel.messageBuilder(MessageTreeTap.class,index)
.encoder(MessageTreeTap::encode)
.decoder(MessageTreeTap::decode)
.consumer(MessageTreeTap::handle)
.add(); index++;
// Send ChunkLoaderTileEntity data to client.
channel.messageBuilder(MessageChunkLoader.class,index)
.encoder(MessageChunkLoader::encode)
.decoder(MessageChunkLoader::decode)
.consumer(MessageChunkLoader::handle)
.add(); index++;
return channel;
}
}
public class MessageChunkLoader
{
private BlockPos pos;
private boolean canLoad;
public MessageChunkLoader(BlockPos pos,boolean canLoad)
{
this.pos = pos;
this.canLoad = canLoad;
}
public void handle(Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
try {
ChunkLoaderBaseTileEntity tile = (ChunkLoaderBaseTileEntity) Minecraft.getInstance().world.getTileEntity(pos);
tile.canLoad = canLoad;
} catch (NullPointerException err) {
System.out.println(String.format("Could not find ChunkLoaderTileEntity at %s %s %s!",pos.getX(),pos.getY(),pos.getZ()));
}
});
}
public static void encode(MessageChunkLoader message, PacketBuffer buffer)
{
buffer.writeBlockPos(message.pos);
buffer.writeBoolean(message.canLoad);
}
public static MessageChunkLoader decode(final PacketBuffer buffer)
{
return new MessageChunkLoader(buffer.readBlockPos(),buffer.readBoolean());
}
}
I then initialize it in my main mod class used by objects in my mod project.
#Mod(Reference.MODID)
public class IntercraftCore
{
public static final SimpleChannel NETWORK = IntercraftPacketHandler.getNetworkChannel();
...
The problem and this post's question; right now I create a new message class from the formula I follow in MessageChunkLoader (public static encode & decode method and a handle method). I would like to create a more generic class for creating message classes for TileEntities, but I'm having problems with that. Here's the current class:
public abstract class MessageTileEntity<T extends TileEntity>
{
protected final BlockPos pos;
protected final Class<T> clazz;
public MessageTileEntity(BlockPos pos, Class<T> clazz)
{
this.pos = pos;
this.clazz = clazz;
}
public abstract void handle(Supplier<NetworkEvent.Context> ctx);
protected T getTileEntity()
{
try {
return clazz.cast(Minecraft.getInstance().world.getTileEntity(pos));
} catch (NullPointerException e) {
System.out.println(String.format("Could not find %s at [%d %d %d]!",clazz.getSimpleName(),pos.getX(),pos.getY(),pos.getZ()));
throw e;
} catch (ClassCastException e) {
System.out.println(String.format("TileEntity at [%d %d %d] is not %s!",pos.getX(),pos.getY(),pos.getZ(),clazz.getSimpleName()));
throw e;
}
}
public static void encode(MessageTileEntity message, PacketBuffer buffer)
{
}
public static MessageTileEntity decode(final PacketBuffer buffer)
{
return null;
}
}
The main problem is I lack the proper Java skills to make it like I want it to function. The method handle is easy as it's non-static and needs to be custom to every TileEntity message, but the methods encode and decode which needs to be static gives me problems. I have no idea what I'm trying to achieve is possible, asking won't hurt. Maybe the solution is easier than I think.

what is '#CalledByNative("...")'?

How do I use #CalledByNative("...")? I need a callback from a webrtc lib.
If you know the class PeerConnection on it:
PeerConnection.java
Here is a old version of PeerConnection but it's almost same now
I call the function addStream, but I can't get the callback from it.
Please explain how calledbynative works!
PeerConnection.java
/*
* Copyright 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
package org.webrtc;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* Java-land version of the PeerConnection APIs; wraps the C++ API
* http://www.webrtc.org/reference/native-apis, which in turn is inspired by the
* JS APIs: http://dev.w3.org/2011/webrtc/editor/webrtc.html and
* http://www.w3.org/TR/mediacapture-streams/
*/
public class PeerConnection {
static {
System.loadLibrary("jingle_peerconnection_so");
}
/** Tracks PeerConnectionInterface::IceGatheringState */
public enum IceGatheringState { NEW, GATHERING, COMPLETE }
/** Tracks PeerConnectionInterface::IceConnectionState */
public enum IceConnectionState {
NEW,
CHECKING,
CONNECTED,
COMPLETED,
FAILED,
DISCONNECTED,
CLOSED
}
/** Tracks PeerConnectionInterface::SignalingState */
public enum SignalingState {
STABLE,
HAVE_LOCAL_OFFER,
HAVE_LOCAL_PRANSWER,
HAVE_REMOTE_OFFER,
HAVE_REMOTE_PRANSWER,
CLOSED
}
/** Java version of PeerConnectionObserver. */
public static interface Observer {
/** Triggered when the SignalingState changes. */
public void onSignalingChange(SignalingState newState);
/** Triggered when the IceConnectionState changes. */
public void onIceConnectionChange(IceConnectionState newState);
/** Triggered when the ICE connection receiving status changes. */
public void onIceConnectionReceivingChange(boolean receiving);
/** Triggered when the IceGatheringState changes. */
public void onIceGatheringChange(IceGatheringState newState);
/** Triggered when a new ICE candidate has been found. */
public void onIceCandidate(IceCandidate candidate);
/** Triggered when some ICE candidates have been removed. */
public void onIceCandidatesRemoved(IceCandidate[] candidates);
/** Triggered when media is received on a new stream from remote peer. */
public void onAddStream(MediaStream stream);
/** Triggered when a remote peer close a stream. */
public void onRemoveStream(MediaStream stream);
/** Triggered when a remote peer opens a DataChannel. */
public void onDataChannel(DataChannel dataChannel);
/** Triggered when renegotiation is necessary. */
public void onRenegotiationNeeded();
}
/** Java version of PeerConnectionInterface.IceServer. */
public static class IceServer {
public final String uri;
public final String username;
public final String password;
/** Convenience constructor for STUN servers. */
public IceServer(String uri) {
this(uri, "", "");
}
public IceServer(String uri, String username, String password) {
this.uri = uri;
this.username = username;
this.password = password;
}
public String toString() {
return uri + "[" + username + ":" + password + "]";
}
}
/** Java version of PeerConnectionInterface.IceTransportsType */
public enum IceTransportsType { NONE, RELAY, NOHOST, ALL }
/** Java version of PeerConnectionInterface.BundlePolicy */
public enum BundlePolicy { BALANCED, MAXBUNDLE, MAXCOMPAT }
/** Java version of PeerConnectionInterface.RtcpMuxPolicy */
public enum RtcpMuxPolicy { NEGOTIATE, REQUIRE }
/** Java version of PeerConnectionInterface.TcpCandidatePolicy */
public enum TcpCandidatePolicy { ENABLED, DISABLED }
/** Java version of PeerConnectionInterface.CandidateNetworkPolicy */
public enum CandidateNetworkPolicy { ALL, LOW_COST }
/** Java version of rtc::KeyType */
public enum KeyType { RSA, ECDSA }
/** Java version of PeerConnectionInterface.ContinualGatheringPolicy */
public enum ContinualGatheringPolicy { GATHER_ONCE, GATHER_CONTINUALLY }
/** Java version of PeerConnectionInterface.RTCConfiguration */
public static class RTCConfiguration {
public IceTransportsType iceTransportsType;
public List<IceServer> iceServers;
public BundlePolicy bundlePolicy;
public RtcpMuxPolicy rtcpMuxPolicy;
public TcpCandidatePolicy tcpCandidatePolicy;
public CandidateNetworkPolicy candidateNetworkPolicy;
public int audioJitterBufferMaxPackets;
public boolean audioJitterBufferFastAccelerate;
public int iceConnectionReceivingTimeout;
public int iceBackupCandidatePairPingInterval;
public KeyType keyType;
public ContinualGatheringPolicy continualGatheringPolicy;
public int iceCandidatePoolSize;
public boolean pruneTurnPorts;
public boolean presumeWritableWhenFullyRelayed;
public RTCConfiguration(List<IceServer> iceServers) {
iceTransportsType = IceTransportsType.ALL;
bundlePolicy = BundlePolicy.BALANCED;
rtcpMuxPolicy = RtcpMuxPolicy.NEGOTIATE;
tcpCandidatePolicy = TcpCandidatePolicy.ENABLED;
candidateNetworkPolicy = candidateNetworkPolicy.ALL;
this.iceServers = iceServers;
audioJitterBufferMaxPackets = 50;
audioJitterBufferFastAccelerate = false;
iceConnectionReceivingTimeout = -1;
iceBackupCandidatePairPingInterval = -1;
keyType = KeyType.ECDSA;
continualGatheringPolicy = ContinualGatheringPolicy.GATHER_ONCE;
iceCandidatePoolSize = 0;
pruneTurnPorts = false;
presumeWritableWhenFullyRelayed = false;
}
};
private final List<MediaStream> localStreams;
private final long nativePeerConnection;
private final long nativeObserver;
private List<RtpSender> senders;
private List<RtpReceiver> receivers;
PeerConnection(long nativePeerConnection, long nativeObserver) {
this.nativePeerConnection = nativePeerConnection;
this.nativeObserver = nativeObserver;
localStreams = new LinkedList<MediaStream>();
senders = new LinkedList<RtpSender>();
receivers = new LinkedList<RtpReceiver>();
}
// JsepInterface.
public native SessionDescription getLocalDescription();
public native SessionDescription getRemoteDescription();
public native DataChannel createDataChannel(String label, DataChannel.Init init);
public native void createOffer(SdpObserver observer, MediaConstraints constraints);
public native void createAnswer(SdpObserver observer, MediaConstraints constraints);
public native void setLocalDescription(SdpObserver observer, SessionDescription sdp);
public native void setRemoteDescription(SdpObserver observer, SessionDescription sdp);
public native boolean setConfiguration(RTCConfiguration config);
public boolean addIceCandidate(IceCandidate candidate) {
return nativeAddIceCandidate(candidate.sdpMid, candidate.sdpMLineIndex, candidate.sdp);
}
public boolean removeIceCandidates(final IceCandidate[] candidates) {
return nativeRemoveIceCandidates(candidates);
}
public boolean addStream(MediaStream stream) {
boolean ret = nativeAddLocalStream(stream.nativeStream);
if (!ret) {
return false;
}
localStreams.add(stream);
return true;
}
public void removeStream(MediaStream stream) {
nativeRemoveLocalStream(stream.nativeStream);
localStreams.remove(stream);
}
public RtpSender createSender(String kind, String stream_id) {
RtpSender new_sender = nativeCreateSender(kind, stream_id);
if (new_sender != null) {
senders.add(new_sender);
}
return new_sender;
}
// Note that calling getSenders will dispose of the senders previously
// returned (and same goes for getReceivers).
public List<RtpSender> getSenders() {
for (RtpSender sender : senders) {
sender.dispose();
}
senders = nativeGetSenders();
return Collections.unmodifiableList(senders);
}
public List<RtpReceiver> getReceivers() {
for (RtpReceiver receiver : receivers) {
receiver.dispose();
}
receivers = nativeGetReceivers();
return Collections.unmodifiableList(receivers);
}
public boolean getStats(StatsObserver observer, MediaStreamTrack track) {
return nativeGetStats(observer, (track == null) ? 0 : track.nativeTrack);
}
// Starts recording an RTC event log. Ownership of the file is transfered to
// the native code. If an RTC event log is already being recorded, it will be
// stopped and a new one will start using the provided file. Logging will
// continue until the stopRtcEventLog function is called. The max_size_bytes
// argument is ignored, it is added for future use.
public boolean startRtcEventLog(int file_descriptor, int max_size_bytes) {
return nativeStartRtcEventLog(file_descriptor, max_size_bytes);
}
// Stops recording an RTC event log. If no RTC event log is currently being
// recorded, this call will have no effect.
public void stopRtcEventLog() {
nativeStopRtcEventLog();
}
// TODO(fischman): add support for DTMF-related methods once that API
// stabilizes.
public native SignalingState signalingState();
public native IceConnectionState iceConnectionState();
public native IceGatheringState iceGatheringState();
public native void close();
public void dispose() {
close();
for (MediaStream stream : localStreams) {
nativeRemoveLocalStream(stream.nativeStream);
stream.dispose();
}
localStreams.clear();
for (RtpSender sender : senders) {
sender.dispose();
}
senders.clear();
for (RtpReceiver receiver : receivers) {
receiver.dispose();
}
receivers.clear();
freePeerConnection(nativePeerConnection);
freeObserver(nativeObserver);
}
private static native void freePeerConnection(long nativePeerConnection);
private static native void freeObserver(long nativeObserver);
private native boolean nativeAddIceCandidate(
String sdpMid, int sdpMLineIndex, String iceCandidateSdp);
private native boolean nativeRemoveIceCandidates(final IceCandidate[] candidates);
private native boolean nativeAddLocalStream(long nativeStream);
private native void nativeRemoveLocalStream(long nativeStream);
private native boolean nativeGetStats(StatsObserver observer, long nativeTrack);
private native RtpSender nativeCreateSender(String kind, String stream_id);
private native List<RtpSender> nativeGetSenders();
private native List<RtpReceiver> nativeGetReceivers();
private native boolean nativeStartRtcEventLog(int file_descriptor, int max_size_bytes);
private native void nativeStopRtcEventLog();
}
#CallByNative is an annotation used by the Google WebRtc Development team to specify mappings between Java and Native (C/C++) Stacks of WebRtc.
As said on there official WebRtc Chromium Git representation such as:
#CalledByNative is used by the JNI generator to create the necessary
JNI bindings and expose this method to native code.
Now if there is a question that how is it happening? How WebRtc Java code is inter-linked with WebRtc Native Code?
For this, I will suggest looking into the Native Code of WebRtc will help you most. You will learn more informative and relevant stuff from the Comments inside the native stack. On the other hand, you should also have the basic knowledge of
How Java Native Interface (JNI) works
How WebRtc Java and Native Stack is interrelated
To get detailed intuition of Java Native Interface, you can visit these references:
Java Native Interface Specification Contents
Java Native Interface Tips
Here I am giving you an example from PeerConnection.java. Let's say, we have a method inside PeerConnection.java class such as:
#CalledByNative("IceGatheringState")
static IceGatheringState fromNativeIndex(int nativeIndex) {
return values()[nativeIndex];
}
Now this method is mapped inside src/sdk/android/src/jni/pc/peer_connection.cc class such as:
static ScopedJavaLocalRef<jobject> JNI_PeerConnection_IceGatheringState(
JNIEnv* env,
const JavaParamRef<jobject>& j_pc) {
return Java_IceGatheringState_fromNativeIndex(
env, ExtractNativePC(env, j_pc)->ice_gathering_state());
}
If you follow the same technique by looking into both Java and Native Class of PeerConnection, you must found some other linkages of that kind. Now, what #CallByNative did here?
If you look, after loading library, #CallByNative basically do these two things such as:
Tells which inner class the method belongs to
Expose this Java method to the Native Code
Make JNI Bindings with Java and Native Code
These types of annotations are provided by Google Developers to make JNI easy and understandable while working with Pre-built libraries or your own compiled libraries such as libwebrtc.aar.
I did some investigation on this topic lately and I would like to share my results. I realized that it might have to do something with #Override methods and the "super" keyword in Java. I suppose when we try to call e.g. the override method onIceCandidate or onAddStream, which is located in the PeerConnection.java file, from the MainActivity.java class we write:
public class MainActivity extends AppCompatActivity implements View.OnClickListener, SignallingClient.SignalingInterface {
...
private void createPeerConnection() {
...
#Override
public void onIceCandidate(IceCandidate iceCandidate) {
super.onIceCandidate(iceCandidate);
onIceCandidateReceived(iceCandidate);
}
#Override
public void onAddStream(MediaStream mediaStream) {
showToast("Received Remote stream");
super.onAddStream(mediaStream);
gotRemoteStream(mediaStream);
}
...
}
...
}
Furthermore, the onAddStream and onIceCandidate are both override methods. If we trace those methods back by the help of the super keyword we get into the following file CustomPeerConnectionObserver.java:
class CustomPeerConnectionObserver implements PeerConnection.Observer {
...
#Override
public void onIceCandidate(IceCandidate iceCandidate) {
Log.d(logTag, "onIceCandidate() called with: iceCandidate = [" + iceCandidate + "]");
}
...
#Override
public void onAddStream(MediaStream mediaStream) {
Log.d(logTag, "onAddStream() called with: mediaStream = [" + mediaStream + "]");
}
...
}
At this point when we take a look at the class we see that it "implements" the PeerConnection.Observer. If we keep investigating a bit further, we realize that we are guided to our file PeerConnection.java:
public class PeerConnection {
...
public interface Observer {
...
#CalledByNative("Observer")
void onIceCandidate(IceCandidate var1);
...
#CalledByNative("Observer")
void onAddStream(MediaStream var1);
...
}
...
}
We get into the "interface" called Observer. So far I took the example from GitHub and I tried to comprehend how the application works. It is for Android, but I suppose we use Java, so there should not be a huge difference, correct me if I am wrong.
In conclusion, I suppose it somehow gets called automatically when a special event occurs and/or when it is mentioned/written as a #Override method, where we need it to be called. I also assume that the #CalledByNative tag could have impact on the method calls, i.e. addStream, also respectively in the example I provided above:
onIceCandidate
onAddStream.
I hope I was able to at least give you some reference points about my investigation on this behaviour, where you could pick up the trace and make further research. I am also looking forward that an expert could answer this good question on how #CalledByNative works.

Transaction for POJOs

I'm implementing a method that does something like:
...
try {
myPojo.setProperty("foo");
myService.execute(myPojo);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
...
If some exception is thrown by my service from this try block on pojo property will have the new value. Is there some way to start a kind of transaction for pojo changes and roll it back if something goes wrong?
Something like:
PojoTransaction pt = startPojoTransaction();
transactionedPojo = pt.handleByTransaction(myPojo);
try {
transactionedPojo.setProperty("foo");
myService.execute(transactionedPojo);
pt.commit;
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
Or something similar...
Take a look at the Memento Pattern, it includes a Java example.
http://en.wikipedia.org/wiki/Memento_pattern
I toyed around with the idea, this is far from perfect, just a simple proof of concept. There are pitfalls in this implementation:
It only tries to call a parameterless constructor of the given source
object to create the target-copy, would need some logic to select a correct constructor (or only support Cloneables?)
Only copies fields declared in the class, not from superclasses (this problem can be solved walking through the inheritance tree and copying any superclass fields)
If the fields are complex types, only the references are copied to target-object, so any changes to them will not be transactional, as both the source and target share the same instance (solvable by recursively creating copies of nested objects and copying their values, requires walking through the entire object-graph, starting from source, and then doing it vice-versa on commit-time)
But, improving from here, I believe it could become very usable. Here's the POC:
import java.lang.reflect.Field;
import org.junit.Assert;
import org.junit.Test;
public class PojoTransactionTest
{
public static class PojoTransaction<T>
{
/**
* This is the original (unmodified) object
*/
private T source;
/**
* This is the object modified by within the transaction
*/
private T target;
/**
* Creates a new transaction for the given source object
* #param source Source object to modify transactionally
*/
public PojoTransaction(T source)
{
try
{
this.source = source;
this.target = (T)source.getClass().newInstance(); //Note: this only supports parameterless constructors
copyState(source, target);
}
catch(Exception e)
{
throw new RuntimeException("Failed to create PojoTransaction", e);
}
}
/**
* Copies state (member fields) from object to another
* #param from Object to copy from
* #param to Object to copy to
* #throws IllegalAccessException
*/
private void copyState(T from, T to) throws IllegalAccessException
{
//Copy internal state to target, note that this will NOT copy fields from superclasses
for(Field f : from.getClass().getDeclaredFields())
{
f.setAccessible(true);
f.set(to, f.get(from));
}
}
/**
* Returns the transaction target object, this is the one you should modify during transaction
* #return Target object
*/
public T getTransactionTarget()
{
return target;
}
/**
* Copies the changes from target object back to original object
*/
public void commit()
{
try
{
copyState(target, source);
}
catch(Exception e)
{
throw new RuntimeException("Failed to change state of original object", e);
}
}
}
public static class TestData
{
private String strValue = "TEST";
private int intValue = 1;
private float floatValue = 3.1415f;
public String getStrValue()
{
return strValue;
}
public void setStrValue(String strValue)
{
this.strValue = strValue;
}
public int getIntValue()
{
return intValue;
}
public void setIntValue(int intValue)
{
this.intValue = intValue;
}
public float getFloatValue()
{
return floatValue;
}
public void setFloatValue(float floatValue)
{
this.floatValue = floatValue;
}
}
#Test
public void testTransaction()
{
//Create some test data
TestData orig = new TestData();
//Create transaction for the test data, get the "transaction target"-object from transaction
PojoTransaction<TestData> tx = new PojoTransaction<TestData>(orig);
TestData target = tx.getTransactionTarget();
target.setFloatValue(1.0f);
target.setIntValue(5);
target.setStrValue("Another string");
//Original object is still at the original values
Assert.assertEquals(1, orig.getIntValue());
Assert.assertEquals(3.1415f, orig.getFloatValue(), 0.001f);
Assert.assertEquals("TEST", orig.getStrValue());
//Commit transaction
tx.commit();
//The "orig"-object should now have the changes made to "transaction target"-object
Assert.assertEquals(5, orig.getIntValue());
Assert.assertEquals(1.0f, orig.getFloatValue(), 0.001f);
Assert.assertEquals("Another string", orig.getStrValue());
}
}
The question is a bit vague, but it sounds like you are wrestling with the basic design pattern for transaction management. You would benefit greatly from the experience that has gone into the production of the pattern used here:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html
Perhaps Spring Transaction management would suit you well for your project anyway.

Help with understanding a function object or functor in Java

Can someone explain what a functor is and provide a simple example?
A function object is just that. Something which is both an object and a function.
Aside: calling a function object a "functor" is a serious abuse of the term: a different kind of "functors" are a central concept in mathematics, and one that has a direct role in computer science (see "Haskell Functors"). The term is also used in a slightly different way in ML, so unless you are implementing one of these concepts in Java (which you can!) please stop using this terminology. It makes simple things complicated.
Back to the answer:
Java does not have "first class functions" that is to say, you can not pass a function as an argument to a function. This true at multiple levels, syntactically, in the byte code representation, and in that the type system lacks the "function constructor"
In other words, you can't write something like this:
public static void tentimes(Function f){
for(int i = 0; i < 10; i++)
f();
}
...
public static void main{
...
tentimes(System.out.println("hello"));
...
}
This is really annoying, since we want to be able to do things like have Graphical User Interface libraries where you can associate a "callback" function with clicking on a button.
So what do we do?
Well, the general solution (discussed by the other posters) is to define an interface with a single method that we can call. For example, Java uses an interface called Runnable for these kinds of things all the time, it looks like:
public interface Runnable{
public void run();
}
now, we can rewrite my example from above:
public static void tentimes(Runnable r){
for(int i = 0; i < 10; i++)
r.run();
}
...
public class PrintHello implements Runnable{
public void run{
System.out.println("hello")
}
}
---
public static void main{
...
tentimes(new PrintHello());
...
}
Obviously, this example is contrived. We could make this code a little bit nicer using anonymous inner classes, but this gets the general idea.
Here is where this breaks down: Runnable is only usable for functions that don't take any arguments, and don't return anything useful, so you end up defining a new interface for each job. For example, the interface Comparator in Mohammad Faisal's answer. Providing a more general approach, and one that takes syntax, is a major goal for Java 8 (The next version of Java), and was heavily pushed to be included in Java 7. This is called a "lambda" after the function abstraction mechanism in the Lambda Calculus. Lambda Calculus is both (perhaps) the oldest programming language, and the theoretical basis of much of Computer Science. When Alonzo Church (one of the main founders of computer science) invented it, he used the Greek letter lambda for functions, hence the name.
Other languages, including the functional language (Lisp, ML, Haskell, Erlang, etc), most of the major dynamic languages (Python, Ruby, JavaScript, etc) and the other application languages (C#, Scala, Go, D, etc) support some form of "Lambda Literal." Even C++ has them now (since C++11), although in that case they are somewhat more complicated because C++ lacks automatic memory management, and won't save your stack frame for you.
A functor is an object that's a function.
Java doesn't have them, because functions aren't first-class objects in Java.
But you can approximate them with interfaces, something like a Command object:
public interface Command {
void execute(Object [] parameters);
}
Updated on 18-Mar-2017:
Since I first wrote this JDK 8 has added lambdas. The java.util.function package has several useful interfaces.
From every-time checks, to Functors, to Java 8 Lambdas (sort of)
The problem
Take this example class, which adapts an Appendable into a Writer:
import java.io.Closeable;
import java.io.Flushable;
import java.io.IOException;
import java.io.Writer;
import java.util.Objects;
/**
<P>{#code java WriterForAppendableWChecksInFunc}</P>
**/
public class WriterForAppendableWChecksInFunc extends Writer {
private final Appendable apbl;
public WriterForAppendableWChecksInFunc(Appendable apbl) {
if(apbl == null) {
throw new NullPointerException("apbl");
}
this.apbl = apbl;
}
//Required functions, but not relevant to this post...START
public void write(char[] a_c, int i_ndexStart, int i_ndexEndX) throws IOException {
public Writer append(char c_c) throws IOException {
public Writer append(CharSequence text) throws IOException {
public Writer append(CharSequence text, int i_ndexStart, int i_ndexEndX) throws IOException {
//Required functions, but not relevant to this post...END
public void flush() throws IOException {
if(apbl instanceof Flushable) {
((Flushable)apbl).flush();
}
}
public void close() throws IOException {
flush();
if(apbl instanceof Closeable) {
((Closeable)apbl).close();
}
}
}
Not all Appendables are Flushable or Closeable, but those that are, must also be closed and flushed. The actual type of the Appendable object must therefore be checked in every call to flush() and close() and, when it is indeed that type, it is casted and the function is called.
Admittedly, this isn't the greatest example, since close() is only called once per-instance, and flush() isn't necessarily called that often either. Also, instanceof, while reflective, is not too bad given this particular example-usage. Still, the concept of having to check something everytime you need to do something else is a real one, and avoiding these "every-time" checks, when it really matters, provides significant benefits.
Move all "heavy duty" checks to the constructor
So where do you start? How do you avoid these checks without compromising your code?
In our example, the easiest step is to move all instanceof checks to the constructor.
public class WriterForAppendableWChecksInCnstr extends Writer {
private final Appendable apbl;
private final boolean isFlshbl;
private final boolean isClsbl;
public WriterForAppendableWChecksInCnstr(Appendable apbl) {
if(apbl == null) {
throw new NullPointerException("apbl");
}
this.apbl = apbl;
isFlshbl = (apbl instanceof Flushable);
isClsbl = (apbl instanceof Closeable);
}
//write and append functions go here...
public void flush() throws IOException {
if(isFlshbl) {
((Flushable)apbl).flush();
}
}
public void close() throws IOException {
flush();
if(isClsbl) {
((Closeable)apbl).close();
}
}
}
Now that these "heavy duty" checks are done only once, only boolean checks need to be done by flush() and close(). While certainly an improvement, how can these in-function checks be eliminated entirely?
If only you could somehow define a function which could be stored by the class and then used by flush() and close()...
public class WriterForAppendableWChecksInCnstr extends Writer {
private final Appendable apbl;
private final FlushableFunction flshblFunc; //If only!
private final CloseableFunction clsblFunc; //If only!
public WriterForAppendableWChecksInCnstr(Appendable apbl) {
if(apbl == null) {
throw new NullPointerException("apbl");
}
this.apbl = apbl;
if(apbl instanceof Flushable) {
flshblFunc = //The flushable function
} else {
flshblFunc = //A do-nothing function
}
if(apbl instanceof Closeable) {
clsblFunc = //The closeable function
} else {
clsblFunc = //A do-nothing function
}
}
//write and append functions go here...
public void flush() throws IOException {
flshblFunc(); //If only!
}
public void close() throws IOException {
flush();
clsblFunc(); //If only!
}
}
But passing functions is not possible...at least not until Java 8 Lambdas. So how do you do it in pre-8 versions of Java?
Functors
With a Functor. A Functor is basically a Lambda, but one that is wrapped in an object. While functions cannot be passed into other functions as parameters, objects can. So essentially, Functors and Lambdas are a ways to pass around functions.
So how can we implement a Functor into our writer-adapter? What we know is that close() and flush() are only useful with Closeable and Flushable objects. And that some Appendables are Flushable, some Closeable, some neither, some both.
Therefore, we can store a Flushable and Closeable object at the top of the class:
public class WriterForAppendable extends Writer {
private final Appendable apbl;
private final Flushable flshbl;
private final Closeable clsbl;
public WriterForAppendable(Appendable apbl) {
if(apbl == null) {
throw new NullPointerException("apbl");
}
//Avoids instanceof at every call to flush() and close()
if(apbl instanceof Flushable) {
flshbl = apbl; //This Appendable *is* a Flushable
} else {
flshbl = //?????? //But what goes here????
}
if(apbl instanceof Closeable) {
clsbl = apbl; //This Appendable *is* a Closeable
} else {
clsbl = //?????? //And here????
}
this.apbl = apbl;
}
//write and append functions go here...
public void flush() throws IOException {
flshbl.flush();
}
public void close() throws IOException {
flush();
clsbl.close();
}
}
The "every-time" checks have now been eliminated. But when the Appendable is not a Flushable or not a Closeable, what should be stored?
Do nothing Functors
A do nothing Functor...
class CloseableDoesNothing implements Closeable {
public void close() throws IOException {
}
}
class FlushableDoesNothing implements Flushable {
public void flush() throws IOException {
}
}
...which can be implemented as an anonymous inner class:
public WriterForAppendable(Appendable apbl) {
if(apbl == null) {
throw new NullPointerException("apbl");
}
this.apbl = apbl;
//Avoids instanceof at every call to flush() and close()
flshbl = ((apbl instanceof Flushable)
? (Flushable)apbl
: new Flushable() {
public void flush() throws IOException {
}
});
clsbl = ((apbl instanceof Closeable)
? (Closeable)apbl
: new Closeable() {
public void close() throws IOException {
}
});
}
//the rest of the class goes here...
}
To be most efficient, these do-nothing functors should be implemented as static final objects. And with that, here is the final version of our class:
package xbn.z.xmpl.lang.functor;
import java.io.Closeable;
import java.io.Flushable;
import java.io.IOException;
import java.io.Writer;
public class WriterForAppendable extends Writer {
private final Appendable apbl;
private final Flushable flshbl;
private final Closeable clsbl;
//Do-nothing functors
private static final Flushable FLUSHABLE_DO_NOTHING = new Flushable() {
public void flush() throws IOException {
}
};
private static final Closeable CLOSEABLE_DO_NOTHING = new Closeable() {
public void close() throws IOException {
}
};
public WriterForAppendable(Appendable apbl) {
if(apbl == null) {
throw new NullPointerException("apbl");
}
this.apbl = apbl;
//Avoids instanceof at every call to flush() and close()
flshbl = ((apbl instanceof Flushable)
? (Flushable)apbl
: FLUSHABLE_DO_NOTHING);
clsbl = ((apbl instanceof Closeable)
? (Closeable)apbl
: CLOSEABLE_DO_NOTHING);
}
public void write(char[] a_c, int i_ndexStart, int i_ndexEndX) throws IOException {
apbl.append(String.valueOf(a_c), i_ndexStart, i_ndexEndX);
}
public Writer append(char c_c) throws IOException {
apbl.append(c_c);
return this;
}
public Writer append(CharSequence c_q) throws IOException {
apbl.append(c_q);
return this;
}
public Writer append(CharSequence c_q, int i_ndexStart, int i_ndexEndX) throws IOException {
apbl.append(c_q, i_ndexStart, i_ndexEndX);
return this;
}
public void flush() throws IOException {
flshbl.flush();
}
public void close() throws IOException {
flush();
clsbl.close();
}
}
This particular example comes from this question on stackoverflow. A fully working, and fully-documented version of this example (including a testing function) can be found at the bottom of that question-post (above the answer).
Implementing Functors with an Enum
Leaving our Writer-Appendable example, let's take a look at another way to implement Functors: with an Enum.
As an example, this enum has a move function for each cardinal direction:
public enum CardinalDirection {
NORTH(new MoveNorth()),
SOUTH(new MoveSouth()),
EAST(new MoveEast()),
WEST(new MoveWest());
private final MoveInDirection dirFunc;
CardinalDirection(MoveInDirection dirFunc) {
if(dirFunc == null) {
throw new NullPointerException("dirFunc");
}
this.dirFunc = dirFunc;
}
public void move(int steps) {
dirFunc.move(steps);
}
}
Its constructor requires a MoveInDirection object (which is an interface, but could also be an abstract class):
interface MoveInDirection {
void move(int steps);
}
There are naturally four concrete implementations of this interface, one per direction. Here is a trivial implementation for north:
class MoveNorth implements MoveInDirection {
public void move(int steps) {
System.out.println("Moved " + steps + " steps north.");
}
}
Using this Functor is done with this simple call:
CardinalDirection.WEST.move(3);
Which, in our example, outputs this to the console:
Moved 3 steps west.
And here is a full working example:
/**
<P>Demonstrates a Functor implemented as an Enum.</P>
<P>{#code java EnumFunctorXmpl}</P>
**/
public class EnumFunctorXmpl {
public static final void main(String[] ignored) {
CardinalDirection.WEST.move(3);
CardinalDirection.NORTH.move(2);
CardinalDirection.EAST.move(15);
}
}
enum CardinalDirection {
NORTH(new MoveNorth()),
SOUTH(new MoveSouth()),
EAST(new MoveEast()),
WEST(new MoveWest());
private final MoveInDirection dirFunc;
CardinalDirection(MoveInDirection dirFunc) {
if(dirFunc == null) {
throw new NullPointerException("dirFunc");
}
this.dirFunc = dirFunc;
}
public void move(int steps) {
dirFunc.move(steps);
}
}
interface MoveInDirection {
void move(int steps);
}
class MoveNorth implements MoveInDirection {
public void move(int steps) {
System.out.println("Moved " + steps + " steps north.");
}
}
class MoveSouth implements MoveInDirection {
public void move(int steps) {
System.out.println("Moved " + steps + " steps south.");
}
}
class MoveEast implements MoveInDirection {
public void move(int steps) {
System.out.println("Moved " + steps + " steps east.");
}
}
class MoveWest implements MoveInDirection {
public void move(int steps) {
System.out.println("Moved " + steps + " steps west.");
}
}
Output:
[C:\java_code]java EnumFunctorXmpl
Moved 3 steps west.
Moved 2 steps north.
Moved 15 steps east.
I haven't started with Java 8 yet, so I can't write the Lambdas section yet :)
Take concept of function application
f.apply(x)
Inverse
x.map(f)
Call x a functor
interface Functor<T> {
Functor<R> map(Function<T, R> f);
}

Automatically opening and closing connection

NOTE: Please ignore my use of MultivaluedMap instead of multiple vargs String...args.
Is there a standard way in java of doing this?
What I have is a resource, that is returned from a remote server. But before each query, the remote connection must be open, and after the returns are returned - it must be closed.
So a natural way of doing this is something like:
Connection c = config.configureConnection();
c.open(); //open
List<Car> cars;
try{
cars = c.getCars();
}finally{
c.close(); //close
}
Now I want to implement something that operates on the level of the resources themselves, without worrying about connection, for example:
List<Car> cars = new CarResource().all(); //opens and closes connection
The way I am currently doing it is by having one abstract class, AbstractQueriable call abstract methods query(String ...args) and query(int id), which any class extending it must implement.
The AbstractQuerieable implements the Queriable interface, which makes it expose the three public methods filter(String ...args), all() and get(int id) - which are the public facing methods.
Here is the Queriable interface:
public interface Queriable <T>{
public T get(String id);
/** Simply returns all resources */
public Collection<T> all();
public Collection<T> filter(MultivaluedMap<String, String> args);
}
here is the AbstractQueriable class that implements it:
public abstract class AbstractQueriable<T> implements Queriable<T> {
#Override
public final T get(String id) {
setup();
try {
return query(id);
} finally {
cleanup();
}
}
#Override
public final Collection<T> filter(MultivaluedMap<String, String> args) {
setup();
try {
return query(args);
} finally {
cleanup();
}
}
/**
* Returns all resources.
*
* This is a convenience method that is equivalent to passing an empty
* arguments list to the filter function.
*
* #return The collection of all resources if possible
*/
#Override
public final Collection<T> all() {
return filter(null);
}
/**
* Queries for a resource by id.
*
* #param id
* id of the resource to return
* #return
*/
protected abstract T query(String id);
/**
* Queries for a resource by given arguments.
*
* #param args
* Map of arguments, where each key is the argument name, and the
* corresponing values are the values
* #return The collection of resources found
*/
protected abstract Collection<T> query(MultivaluedMap<String, String> args);
private void cleanup() {
Repository.close();
}
private void setup() {
Repository.open();
}
and finally my resource, which I want to use in the code, must extend the AbstractQueriable class, for example (please note that the details of these methods are not important):
public class CarRepositoryResource extends AbstractQueriable<Car> {
#Override
protected Car query(String id) {
MultivaluedMap<String, String> params = new MultivaluedMapImpl();
params.add("CarID", id);
// Delegate the query to the parametarized version
Collection<cars> cars = query(params);
if (cars == null || cars.size() == 0) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
if (cars.size() > 1) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return cars.iterator().next();
}
#Override
protected Collection<Car> query(MultivaluedMap<String, String> params) {
Collection<Car> cars = new ArrayList<Car>();
Response response = Repository.getConnection().doQuery("Car");
while (response.next()) {
Returned returned = response.getResult();
if (returned != null) {
cars.add(returned);
}
}
return cars;
}
}
which finally, I can use in my code:
Collection<Car> cars = new CarRepositoryResource().all();
//... display cars to the client etc...
There are a few things I don't like about this kind of setup:
I must instantiate a new instance of my "CarRepositoryResource" every time I do a query.
The method names "query", while internal and private, are still confusing and clunky.
I am not sure if there is a better pattern or framework out there.
The connection that I am using does not support/implement the JDBC api and is not sql-based.
You could use a variation of the (in)famous Open session in view pattern.
Basically it comes down to this:
Define a "context" in which connections are available
(usually the request in web applications)
Handle (possibly lazy) initialization and release of a connection when entering/exiting the context
Code your methods taking for granted they will only be used inside such a context
It is not difficult to implement (storing the connection in a static ThreadLocal to make it thread safe) and will definitely spare a few open/close calls (performance-wise that could be a big gain, depending on how heavy your connection is).
The context class could look something like (consider this pseudo-code);
public class MyContext{
private static final
ThreadLocal<Connection> connection = new ThreadLocal<Connection>();
public static void enter() {
connection.set(initializeConnection());
// this is eager initialization
// if you think it will often the case that no connection is actually
// required inside a context, you can defer the actual initialization
// until the first call to get()
}
public static void exit() {
try { connection.close(); }
catch(Throwable t) { /* panic! */ }
finally { connection.set(null); }
}
public static Connection get() {
Connection c = connection.get();
if (c == null) throw new IllegalStateException("blah blah");
return c;
}
}
Then you would use connections like this:
MyContext.enter();
try {
// connections are available here:
// anything that calls MyContext.get()
// gets (the same) valid connection instance
} finally {
MyContext.exit();
}
This block can be put wherever you want (in webapps it usually wraps the processing of each request) - from the main method if you are coding a simple case when you want a single connection available for the whole lifespan of your application, to the finest methods in your API.
You might want to take a look at fluent interfaces (with an interesting example here) and its "Builder" pattern.
You would query like this:
cars().in(DB).where(id().isEqualTo(1234));
This way you can hide the connection/disconnection code in the outermost cars() method, for example.

Categories