To celebrate this new year and experiment our new more frequent release cycle, we have just released GraniteDS 3.0.1.GA. It comes with a few important bug fixes and some improvements in the documentation. See the release notes , we strongly recommend to upgrade if you are currently using any earlier 3.0.x version. Notably there was a critical issue when using GraniteDS with Apache Flex 4.10+.
The distribution is available for download here, and artifacts are available on Maven Central .
We have already explained our new licensing model a few times in previous posts, but to summarize:
You can freely use the GPL 3.0 license if your code is released under any compatible open source license. In any other case you have to purchase a commercial license for the modules you are using. See the complete licensing options here, and note that you can pay your license online in just a few minutes using Paypal or a payment card.
Finally we have changed our professional support packages with more flexible options and pricing so there should be no reason why we cannot find a way to help you!
And if you didn’t notice, you are right now visiting our brand new !
As always, any feedback appreciated.
]]>We have spent quite some time to completely rework the tool chain for the project, with a new build system based on , a new documentation generated with , and new multi-technologies focused on specific tasks.
The content is not yet perfect, but at least we now have a really good and modern infrastructure. This heavy lifting had long been needed and will now help us bring more frequent releases. It will also make much easier to contribute to the project, either code, docs or tutorials by simple pull requests in github.
All server and basic libraries are now released under the LGPL 2.1 (previously LGPL 2.0), and all advanced client libraries and UDP client and server integration are now released under a dual GPL 3.0 / commercial license. See here for more details on the commercial licenses.
GraniteDS 3.0.0 brings a new Java client implementation compatible with both GDS 2.3 and GDS 3.0 servers. It also provides support for (almost) all Tide framework features on JavaFX 2.2+.
Additionally GraniteDS brings the new binary protocol JMF which specifically targets Java client to Java server communication and avoids serialization issues with both AMF and Java serialization.
Websocket channels are available for all supported client technologies (Flex, Java, JavaFX, Android). GraniteDS uses the native support of the application servers, so Tomcat 7, Jetty 8.1+ (but not yet Jetty 9) and GlassFish 3.1.2+ can be used. The next release will add support for the standard websocket JSR 356 and Servlet 3.1.
Some messaging use cases do not very well fit with TCP-based communication protocols. UDP messaging is now available for usages that require very fast non guaranteed data transfer, such as continuous price updates for trading applications or transmission of player positions for gaming.
UDP channels are available for all supported client technologies (Flex, Java, Android) and all application servers.
Usually the modifications on object graphs by users on the client concern only a few properties. It is thus excessive to transfer the complete object graph to the server for doing the update. Incremental updates (changeSets) allow to send only the modified values and greatly limit the quantity of data to transfer. This is supported in the client to server direction and when using Hibernate, also server to client data transfers.
There has been until now a limitation to only one remote server application at a time with the Flex Tide API, it is now possible to use the Tide API with as many servers as needed by using the ServerSession API.
You will find the complete list .
Merry Christmas!! And don’t hesitate to give your feedback and comments here or on the .
The GraniteDS Team.
]]>Several packages have been renamed to a more consistent convention under the prefix ‘org.granite.client.javafx’. Usually a simple ‘Optimize imports’ or search/replace in your IDE should be enough to do the necessary changes.
The ChannelFactory API has been slighly changed to allow different channel types:
ChannelFactory channelFactory = new JMFChannelFactory(); channelFactory.start(); MessagingChannel channel = channelFactory.newMessagingChannel(ChannelType.LONG_POLLING, "longPollingChannel", "http://localhost:8080/gravityamf/amf.txt") Consumer consumer = new Consumer(channel, "stocks", "europe");
For a websocket channel, you will also have to configure the transport:
ChannelFactory channelFactory = new JMFChannelFactory(); channelFactory.setMessagingTransport(ChannelType.WEBSOCKET, new JettyWebSocketTransport()); channelFactory.start(); MessagingChannel channel = channelFactory.newMessagingChannel(ChannelType.WEBSOCKET, "websocketChannel", "ws://localhost:8080/myapp/gravityamf/amf"); Consumer consumer = new Consumer(channel, "stocks", "europe");
For a UDP channel, assuming the granite-client-java-udp.jar library is present:
ChannelFactory channelFactory = new JMFChannelFactory(); channelFactory.start(); MessagingChannel channel = channelFactory.newMessagingChannel(ChannelType.UDP, "udpChannel", "http://localhost:8080/myapp/gravityamf/amf.txt") Consumer consumer = new Consumer(channel, "stocks", "europe");
Of course you can mix all these channels and get them from the same ChannelFactory.
Additionally you can use the ServerApp API if you don’t want to build the url yourself:
ServerApp serverApp = new ServerApp("/myapp", false, "localhost", 8080); ChannelFactory channelFactory = new JMFChannelFactory(); channelFactory.start(); MessagingChannel lpChannel = channelFactory.newMessagingChannel(ChannelType.LONG_POLLING, "longPollingChannel", serverApp); MessagingChannel wsChannel = channelFactory.newMessagingChannel(ChannelType.WEBSOCKET, "websocketChannel", serverApp); MessagingChannel udpChannel = channelFactory.newMessagingChannel(ChannelType.UDP, "udpChannel", serverApp);
The ServerSession API has also been updated.
You can now use the ServerSession to build Consumer and Producer objects:
ServerSession serverSession = new ServerSession("/myapp", "localhost", 8080); serverSession.setMessagingTransport(ChannelType.WEBSOCKET, new JettyWebSocketTransport()); serverSession.start(); Consumer lpConsumer = serverSession.getConsumer(ChannelType.LONG_POLLING, "stocks", "europe"); Consumer wsConsumer = serverSession.getConsumer(ChannelType.WEBSOCKET, "stocks", "usa"); Consumer udpConsumer = serverSession.getConsumer(ChannelType.UDP, "stocks", "asia");
The GraniteDS Team.
]]>Tide.getInstance().getContext().serviceInitializer = new DefaultServiceInitializer('/myapp');
Should be replaced by:
Tide.getInstance().mainServerSession.serverApp = new SimpleServerApp('/myapp');
Why this (apparently) cosmetic change ? The difference is that you can now create other ServerSession objects for other server applications (other context roots, other server urls, …). Implicit service proxies will still be routed to the main ServerSession, if you want to connect to another server, you will have to attach the service proxies to the other ServerSession:
Tide.getInstance().mainServerSession.serverApp = new SimpleServerApp('/myapp'); var appSession2:ServerSession = new ServerSession('/myapp2', false, 'myserver2', '8080'); Tide.getInstance().getContext().appSession2 = appSession2; Tide.getInstance().getContext().myService2 = new MyService2(appSession2); // Service proxy for MyService on http://localhost:8080/myapp [Inject] public var myService:MyService; // Service proxy for MyService2 on http://myserver2:8080/myapp2 [Inject] public var myService2:MyService2;
The GraniteDS Team.
]]>The most visible change in this release is the new build process which is now entirely based on Gradle: instead of several Git repositories (one for each module), you will now find everything under a single repository called . The documentation is now based on , a much lighter solution than our previous docbook generation.
This heavy lifting of our build tools was long needed and should help us to bring more frequent releases. It will also make much easier to contribute to the project, either code or docs by simple pull requests in github.
On the technical features side, here are some highlights:
Of course, many other bug fixes and improvements are also packaged in this release and you can find the complete list on Jira.
We plan to release the final 3.0.0 version at early/mid November. The APIs are now final and we won’t add any new feature, but focus only on bug fixes, documentation, examples and tutorials. You are thus invited to use the RC1 as soon as possible and report quickly anything that looks like a bug.
The next major release will introduce at least these new features or improvements:
You can refer to the previous post for the release announcement of 3.0.0.M3 for the new licensing of the different modules. To summarize, all server and basic libraries are now released under the LGPL 2.1 (previously LGPL 2.0), and all advanced client libraries and UDP client and server integration are released under a dual GPL 3.0 / commercial license.
All current users of GraniteDS can send a request at [email protected] for a free one year ‘early bird license’ for all these libraries until the final 3.0.0.GA release.
There have been once again some changes in the client APIs which will require some changes in your code.
Be sure to check our posts about “Migrating from GraniteDS 3.0.0.M3 to 3.0.0.RC1 (Flex)” and “Migrating from GraniteDS 3.0.0.M3 to 3.0.0.RC1 (JavaFX)”.
Comments are welcome,
The GraniteDS Team.
]]>A sample application on Github is a ready to use demonstration of this new feature: follow the instructions on the (README.md).
]]>Basically because we love AMF but AMF isn’t good for Java client applications: with AMF, for example, all Java numeric types (byte, short, int, long, float, double, etc.) are serialized either as ActionScript int or Number, which leads to useless conversions in the context of a Java to Java data exchange and can even lead to a loss of precision (large long values cannot be represented as Numbers without truncation). Furthermore, all collections (java.util.*) are normalized to a single ArrayCollection type, BigDecimals are converted to Numbers, enum values to nothing standard (ActionScript has no enum types), etc.
Using AMF with Java clients is certainly possible, and we do have AMF support for Java clients in GraniteDS, but it is pointlessly complicated and, as a result, requires a full bunch of ugly workarounds.
That said, JMF is largely inspired by AMF and designed with the following goals in mind:
You basically need to do nothing to use JMF: HTTP headers of serialized data, unless you have configured your Java client application to do otherwise, use a specific mime-type which tells the GraniteDS backend to switch to JMF instead of AMF serialization for the incoming request and corresponding response.
The JMF mime-type is currently “application/x-jmf+amf”, the “+amf” part stating that the messages inside the request are instances of flex.messaging.messages.Message (possibly enclosed in an AMF0 envelop). We are considering to use our own message envelops when using JMF and the mime-type is likely going to be “application/x-jmf” only in later versions.
The good thing with this mime-type switch mechanism is that you can have Java (or even JavaFX / Android) client applications using the exact same backend used by Flex client applications: there is nothing specific to configure on the server-side.
With small messages such as a ping message (which purpose is to make sure that the server is alive and to negotiate serialization options), JMF vs. AMF vs. Standard Java Serialization (ie. java.io.ObjectOutputStream) gives these results:
With bigger messages (a list of person with collections of contacts), you can typically get these results:
As a general result, but without conducting an extensive benchmark, we have found that:
AMF serialization doesn’t state anything about what is (de)serializable or not: this lack of control can lead to a security breach that was discovered by Wouter Coekaerts and reported . Granite Data Services fixed this issue by adding a AMF3DeserializerSecurizer that controls which class can be instantiated at deserialization time (see this post about GraniteDS 2.2.1.GA).
Unlike AMF but just like the standard Java serialization, JMF only encodes primitive types and classes that implement java.io.Serializable. As a result, the above vulnerability doesn’t affect JMF, unless classes that shouldn’t be serialized implement (which is a design bug) java.io.Serializable.
Not yet. However, you are free to have look at the implementation, it’s fully open-source, just like the rest of the GraniteDS platform.
]]>This new release is a very important milestone on our way to the final 3.0.0.GA version, both from technical and business point-of-views:
Beside the usual , the 3.0.0.M3 version of our platform brings the following new features (some of them were already present in previous milestones, though at an early development stage):
Our focus for the next release (likely a 3.0.0.RC1) will be on Android, UDP-based real-time messaging and JSON support.
Documentation and tutorials need an update, we will post new resources as soon as they are available.
GraniteDS has always been an avid supporter of open source software. Our business model so far has been to sale yearly subscriptions to an enterprise version of our platform, embedding some very advanced features absent from the community version, together with an access to professional support services.
While we have had and still have some success with this model, it is clearly targeted to mid / big organizations developing critical applications: most of our users are simply using the community version, either because they don’t need any support or can’t afford to pay for our enterprise subscription packages. As a result, generated revenues are below what we need to move to the next step and truly develop and promote GraniteDS in the long run.
After considering different options, we have decided to move to the following business model:
We sincerely hope that you will understand this move, which is, from our point-of-view, pretty fair: open source and free software is great and must stay free for people developing open source software as well. For those who develop commercial software, and unless they can live with the basic features of our platform, an affordable and predictable financial contribution is now asked.
Before asking us any question about this new business model / commercial license, please read our licensing FAQ and the license itself.
In the 3.0.0.M3 release, only the Granite Android and JavaFX Libraries are released under GPL 3.0, with the option of purchasing a commercial license: this includes Tide for Java client applications, but the basic Java client features (eg. low-level remoting and real-time messaging) are still LGPL. Everything else in the platform is LGPL (server-side libraries, Flex client libraries, code generation tools).
Starting with the next 3.0.0.RC1 release, two other products will be available under the same dual-licensing scheme (GPL 3.0 / GraniteDS SLA):
Again, we are and will be offering free commercial licenses for early birds, so it is not going to hurt your wallet if you fast enough (the final 3.0.0.GA won’t be released before early October at the earliest).
Comments are welcome,
The GraniteDS Team.
]]>