Archive for the 'News' Category

Number guess game with continuations

Saturday, November 17th, 2007

We found a nice illustration of using continuations among RIFE examples and wrote the Number guess game also using Aranea Continuations (for the introduction read Aranea and Swing get Continuations).

The following game chooses a random integer between 0 and 100 and lets the user to guess it. Each time a hint is given whether the right answer is higher or lower than the entered:

[code]class NumberGuessingGameExample extends JPanel {

	private static final int MIN = 0;
	private static final int MAX = 100;

	@Resumable
	void init() {
		setLayout(new BorderLayout());

		JLabel label = new JLabel("Guess a number from " + MIN + " to " + MAX);
		JTextField field = new JTextField();
		field.setHorizontalAlignment(JTextField.CENTER);
		JButton button = new JButton("Guess");

		add(label, BorderLayout.NORTH);
		add(field, BorderLayout.CENTER);
		add(button, BorderLayout.SOUTH);
		updateUI();

		int answer = MIN + (int) (Math.random() * (MAX - MIN + 1));
		int guesses = 0;
		int guess = -1;

		while (guess != answer) {
			SwingBlockingUtil.waitForOneAction(button);

			try {
				guess = Integer.parseInt(field.getText());
			} catch (NumberFormatException e) {
				continue;	// ignore
			}

			if (guess < MIN || guess > MAX) {
				continue;	// ignore
			}

			field.setText("");

			if (answer < guess) label.setText("The answer is lower than " + guess);
			if (answer > guess) label.setText("The answer is higher than " + guess);

			guesses++;
		}

		System.out.println("You found the answer " + answer + " by " + guesses + " guesses");
	}

	public static void main(String[] args) {
		NumberGuessingGameExample panel = new NumberGuessingGameExample();
		JFrame frame = new JFrame();
		frame.add(panel);
		panel.init();
	}

}[/code]

Notice that the program consists of one main loop which takes a user input, processes it and gives a response. This is like reading standard input. To do the same in Swing, usually one is forced to register an ActionListener and the program flow jumps to that - different method when an action occurs.

Here waitForOneAction() blocks the program flow until the button receives an action (like java.io.Reader.read()).

Under the hood still an ActionListener is used. When waitForOneAction() is invoked a snapshot is taken from the program exceution and when ActionListener.actionPerformed() is reached this snapshot is used to resume the program.

The whole source code can be accessed at:
http://svn.araneaframework.org/repos/aranea-continuations/

JavaRebel Brings Class Reloading to Java

Monday, October 8th, 2007

Finally we are ready to unveil what Aranea team has been so busy on. As time went by we realized that one of the main problems impeding developer productivity was lack of class reloading facilities in Java Virtual Machine. We have been working on this for almost a year and today we can show the results.

JavaRebel reloads changes to Java classes on-the-fly without redeploy or restart including new methods and fields. It is a generic solution that works for standalone Java applications as well as application servers.

Watch the demonstration screencast (~5 mins), read the feature list or just download JavaRebel from ZeroTurnaround.com and give it a try. Disclaimer: JavaRebel is commercial software with a free trial for 14 days and developer seat cost at 99$.

ZeroTurnaround is a spinoff of Webmedia, Ltd. that focuses on Java developer productivity tools. Currently we are developing JavaRebel, a generic Java class reloader, and JSP Weaver, an instant JSP interpreter.

Aranea-MVC 1.1-M4

Monday, October 1st, 2007

We had somewhat longer gap between releases of M3 and M4 than usual, due to team taking vacation in July and being temporarily involved in three different projects as of late. But now for some highlights of 1.1-M4:

Also, there’s support for context menus in browsers, new control that is hybrid of text and select controls, plus for everyones coding pleasure FormWidget.addElement* and FilterHelper.* methods do not throw checked Exceptions anymore. See full changelog here.

Separate 1.1 demo application is also up. Obviously demos contain more explanations and stuff than mentioned here, so take a look! For everyone who has not yet noticed—already since early 1.0 days there are Widget source and Template source links in our demos (they are not easily spotted sometimes, look at the bottom left corner next to side menu :)).

NB! It was not mentioned in changelog that comes with distro, but StandardFlowContainerWidget (standard implementation of FlowContext) was modified in a way that is incompatible with some older uses. Namely, when call stack is empty and parent FlowContext exists, StandardFlowContainerWidget.finish() and cancel() methods return control to parent FlowContext (meaning that once active StandardFlowContainerWidget is gone for good). In cases (mainly in menus) where this is unwanted, one must take care and call StandardFlowContainerWidget.setFinishable(false).

Aranea-MVC 1.0.11

Friday, August 31st, 2007

1.0.11 fixes issue with FormWidget.restoreBaseState(). There is some more though, details here.

JSP Weaver 1.0 M1

Wednesday, August 22nd, 2007

Although not directly connected to Aranea we are proud to present the first release from our spin-off ZeroTurnaround. The spin-off will focus on increasing developer productivity by reducing development turnaround time.

Our first product JSP Weaver is a JSP interpreter. Usually JSP is first translated to regular Java code and then compiled into a Java servlet. JSP Weaver eliminates the Java generation and compilation stage by interpreting the JSP files on-the-fly. This reduces the time taken to reload a JSP up to 50 times bringing it from seconds down to milliseconds.

Although we will provide full support of JSP standard in the final release, this milestone does not yet include support for the non-XML old style JSP syntax and provides limited support for scriptlets. If you are using XML syntax for your JSPs have a go at it and be amazed by the speedup.

Disclaimer: JSP Weaver is a commercial product that costs about 49$ per developer seat. You can try it out for free with no limitation, but must buy it for development.

Aranea-MVC 1.0.10

Monday, July 30th, 2007

There are quite few changes in this latest update to 1.0 branch, so I will list and comment on them all.

  • BeanFormWidget.readBean() method destroyed the content of sub-beans when writing nested form to a bean. This was both counterintuitive and wrong because the root bean and the child beans were handled differently (root bean fields were only updated, but child beans always created anew). This has been fixed
  • As the naming of BeanFormWidget.readBean() was very confusing, this method is now deprecated in favour of writeToBean(). Analogously, BeanFormWidget.writeBean() is deprecated in favour of readFromBean(). BeanFormWidget’s readBean() and writeBean() will be removed in 1.1 branch.
  • TcdAndTldMerger utility that was distributed only in source form and had to be compiled separately is now included in aranea.jar. Its purpose and usage are documented here.

Aranea Integration 1.0-M1

Thursday, June 28th, 2007

Are you stuck with a Java web application written in an in-house or legacy web framework? Does management point to the costs of rewriting the application, so you have to continue development using outdated techniques and approaches?

Aranea Integration provides the infrastructure for splitting the existing applications into self-contained components, which can then be rewritten one-by-one only when requirements change. This allows spreading the costs of migration over time and continuing new development using a new framework immediately. It also allows developing individual components using any web framework you like, giving access to a wide variety features and approaches.

Aranea Integration 1.0-M1
includes integration with Struts, JSF and GWT. Although the release lacks comprehensive documentation it comes with a lot of examples, as well as a whitepaper. In addition, TheServerSide Java Symposium presentation contains a good deal of info on step-by-step legacy migration, our approach to getting rid painlessly of legacy and custom web frameworks.

Along with the Aranea Integration subproject we have launched commercial support, training and consulting provided by Webmedia, Ltd. and available from www.araneaframework.com.

Aranea-MVC 1.1-M3

Sunday, June 24th, 2007

Most visible and important news about third milestone of Aranea-MVC 1.1 are:

  • pages containing update regions will not sometimes crash with NPE when active flow is finished during request
  • few of the Aranea specific request parameters were renamed (prefix was added). For example: ‘transactionId’ vs ‘araTransactionId’. Unless your custom client-side scripts or server-side filters directly used these parameter names (which should not be the case), this will not affect you.

Full changelog for the curious ones.

Aranea-MVC 1.1-M2 & 1.0.9

Thursday, June 14th, 2007

Those who attend our forums or subscribe to release feeds have already noticed that both stable and development branches saw new releases two days ago. Users of 1.1-M1 should definitely seek upgrade. Sourceforge has it all.

Aranea and Swing get Continuations!

Monday, June 11th, 2007

Aranea Continuations project supports waiting on Swing and Aranea events by introducing high-level API over the JavaFlow library, hiding the mechanics of continuations behind an annotation, blocking calls and an instrumentation agent. Download from SourceForge or read the reference.

Continuations is one of the most hip and misused terms in Java community. Popularized by Geert Bevin and RIFE framework they allow to wait for event to happen and resume the method execution from the point on. A common point of comparison is the readln() DOS function that waited for user to input before resuming. In Java we are interested in waiting on events like user clicking a button.

Support for continuations in generic Java has been available for some time via the JavaFlow library. However their API was relatively low-level and clumsy in day-to-day development. As a part of Aranea Continuations project we built a higher level API on top of it, which can be illustrated by the following Swing example:
[code]
class BlockingSwingExample extends JPanel {
//Method with continuations
@Resumable
public void init() {
JButton button = new JButton(”Click on me!”);
add(button);
updateUI();

for (int i = 1; i <= 10; i++) {
SwingBlockingUtil.waitForOneAction(button);
System.out.println("You have clicked me " + i);
}
System.exit(0);
}

//Swing boilerplate
public static void main(String[] args) {
BlockingSwingExample panel =
new BlockingSwingExample();
JFrame frame = new JFrame();
frame.add(panel);
frame.setVisible(true);
panel.init();
}
}
[/code]

The important part of the Aranea Continuations API is the @Resumable annotation and SwingBlockingUtil.waitForOneAction(button) call. The first one tells that the current method can be resumed later while the second will wait until the listener is called. The code will wait till user clicks the button exactly ten times and then will exit (the example is available with distribution by running ant run-swing-example).

To make the example run we need to instrument the classes bytecode. In addition to the preprocessing supported by JavaFlow we have implemented support for Java Instrumentation API, so it becomes as easy as registering an instrumentation agent:
java -javaagent:aranea-blocking.jar=example example.BlockingSwingExample
To limit preprocessing the agent receives a comma-separated list of the application packages as a argument (in this case the example package).

Aranea Continuations provide support for waiting for Aranea MVC events same way as in Swing. The core API here is the AraneaBlockingUtil. However in addition to events we provide support for invoking flows and waiting for the return value:
[code]
@Resumable
String askForName() {
String result =
AraneaBlockingUtil.call(
getFlowCtx(),
new DialogWidget(”Please enter your name:”));
return result;
}
[/code]
This will display the user a separate page with an input box and return the value of the text box when user submits the form.

Looking under the hood blocking calls are implemented using a simple call/cc semantics:
[code]
static void waitForOneAction(final AbstractButton button) {
BlockingUtil.call(new IndirectCallable() {
void call(final ReturnContext returnCtx) {
final ActionListener[] aListener = new ActionListener[1];
aListener[0] = new ActionListener() {
public void actionPerformed(ActionEvent e) {
button.removeActionListener(aListener[0]);
returnCtx.returnWith(null);
}
};

button.addActionListener(aListener[0]);
}
});
}
[/code]

ReturnContext represents the current continuation that can be called to return from method once or several times:
[code]
public interface ReturnContext {
void returnWith(Object result);
void failWith(Throwable t);
}
[/code]
Using that it is trivial to add support for other events or actions. In fact we only implemented Swing blocking API because we realized how easy it is on top of the existing API.

Nothing comes for free and this is doubly so for bytecode modification. JavaFlow will definitely add a performance penalty to your application. However you should consider that it will almost exclusively add CPU consumption and will not stress IO or memory. This means that in most projects the impact will not be considerable or possibly even noticeable. This goes specially to desktop Swing applications, which are highly unlikely to be CPU-bound. Of course one should stress-test the application to make sure what the impact is in your environment.

The first release is available from SourceForge with a (brief) reference also available. We will continue to improve the project and plan to release as much of changes upstream as we can. We are also looking for contributions supporting blocking calls in other frameworks (like SWT). We would like to express our gratitude to Rein Raudjärv for developing the project and to Oleg Mürk for the original idea.