package client; import java.util.ArrayList; import jstm4gwt.core.Site; import jstm4gwt.core.Transaction; import jstm4gwt.extensions.GWTNotifier; import jstm4gwt.transports.clientserver.ConnectionInfo; import jstm4gwt.transports.clientserver.gwt.GwtClient; import jstm4gwt.ui.Binding; import jstm4gwt.ui.Binding.TextBoxBinding; import client.generated.Form; import client.generated.FormObjectModel; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.*; /** * This sample shows how you can use JSTM to replicate data entered through a * form. If you launch two browsers, modify some fields on the form you can see * the new values appearing on the other side. If you start a transaction, you * can send several changes at once, detect conflicts with other users and abort * your changes to get the form to the state it has before your edits. */ public class MyApplication implements EntryPoint { private Form form; private Button start, commit, abort; private final ArrayList bindings = new ArrayList(); public void onModuleLoad() { /* * It is not possible to use the default notifier which uses a dedicated * thread as threads are not supported in GWT. It is necessary to use * this GWT notifier. */ Site.getLocal().setDefaultNotifier(new GWTNotifier()); /* * Register Form demo object model. */ Site.getLocal().registerObjectModel(FormObjectModel.getInstance()); // Create a JSTM client transport to communicate with the client. GwtClient client = new GwtClient(); client.beginConnect(new AsyncCallback() { public void onSuccess(ConnectionInfo connection) { /* * When connected, start retrieving the object shared by the * server. In GWT this needs to be an asynchronous call. */ connection.getServer().getShare("form", new AsyncCallback() { public void onSuccess(Object result) { form = (Form) result; start(); } public void onFailure(Throwable t) { } }); } public void onFailure(Throwable t) { } }); } private void start() { // For each field of our form, add a label and a TextBox. This will be // our poor man's editable grid. for (int i = 0; i < Form.FIELD_COUNT; i++) { Label label = new Label(Form.getFieldNameStatic(i)); RootPanel.get().add(label); final TextBox textBox = new TextBox(); textBox.setText((String) form.getField(i)); bindings.add(Binding.bind(textBox, form, i)); RootPanel.get().add(textBox); } start = new Button("Start Transaction"); start.addClickListener(new ClickListener() { public void onClick(Widget sender) { Site.getLocal().startTransaction(); onCurrentTransactionChanged(); } }); RootPanel.get().add(start); commit = new Button("Commit"); commit.addClickListener(new ClickListener() { public void onClick(Widget sender) { Transaction.getCurrent().beginCommit(new AsyncCallback() { public void onSuccess(Void result) { Transaction.setCurrent(null); onCurrentTransactionChanged(); } public void onFailure(Throwable t) { Transaction.setCurrent(null); onCurrentTransactionChanged(); restoreFields(); Window.alert("A conflict occurred with changes made by another user."); } }); } }); RootPanel.get().add(commit); abort = new Button("Abort"); abort.addClickListener(new ClickListener() { public void onClick(Widget sender) { Transaction.getCurrent().abort(); onCurrentTransactionChanged(); restoreFields(); } }); RootPanel.get().add(abort); onCurrentTransactionChanged(); } private void onCurrentTransactionChanged() { start.setEnabled(Transaction.getCurrent() == null); commit.setEnabled(Transaction.getCurrent() != null); abort.setEnabled(Transaction.getCurrent() != null); } private void restoreFields() { for (TextBoxBinding binding : bindings) binding.getTextBox().setText((String) form.getField(binding.getFieldIndex())); } }