I'll skip foreplay today and dive into the middle of things. Our goal is to realize
in such a way that the BookSearcher is implemented on the server in Java and BookSearchDialog in the Browser, i.e. using JavaScript.
Let's focus on the Java server side first. Prerequisite is a Java 5 compatible servlet engine (e.g. Tomcat 5.5). First and foremost you define both UML interfaces in terms of Java interfaces:
import jayjax.IFacade; public interface BookSearchPresenter extends IFacade { void search(String searchString); }
import java.util.List; public interface BookSearchView { void displayList(List<Book> resultList); }
I've chosen to use the parameterized version List<Book> resultList in order to make the (not yet existing) implementation of the presenter interface more type-safe. Now you can go ahead and implement the searcher functionality:
import java.util.*; import jayjax.AbstractAjaxFacade; public class BookSearcher extends AbstractAjaxFacade<BookSearchView> implements BookSearchPresenter { public void init() { getView().displayList(new ArrayList<Book>()); } public void search(String searchString) { List<Book> result = calculateSearchResult(searchString); getView().displayList(result); } private List<Book> calculateSearchResult( String searchString) { List<Book> result = new ArrayList<Book>(); // Retrieve list and add book objects to result ... return result; } } public class Book { private String title, author; /** Needed for (de-)serialization */ public Book() {} public Book(String title, String author) { this.title = title; this.author = author; } public String getAuthor() {return author;} public String getTitle() {return title;} }
Mind that class BookSearcher is derived from jayjax.AbstractAjaxFacade. This enables JayJax to hand in the view proxy which can then be accessed within facade implementations via getView(). JayJax will then take care of forwarding all method invocations on the view to the client.
There are a few limitations on how the interfaces can be specified:
presenter.method(par1, par2, ...)
you cannot overload methods since JavaScript cannot have more than one method with the same name. This holds for both, the presenter's and the view's interface.
presenter.method(par1, par2, ... , {onSuccess: processResult});
function processResult(returnValue) { //do something with returnValue }
Now you connect the interfaces and the implementation via an annotation and give it a name (searcher) under which it is accessible from JavaScript:
@AjaxFacade(name="searcher", view=BookSearchView.class, implementation=BookSearcher.class) public interface BookSearchPresenter extends IFacade {...}
In case you've registered the two JayJax servlets and your facade correctly in your web.xml (described in JayJax' documentation) the framework will take care of several things:
Currently JayJax can handle all primitive value as well as a few standard object types like String, java.util.List and java.util.Date. Moreover, objects which are compliant to Java's standard bean convention can also be used. And you have the possibility to define your own (de-)serialization methods if the need arises.
All you have to do to be enable the MVP communication is including a few JavaScript libraries and generated code pages:
<script type="text/javascript" src="js/prototype.js"></script> <script type="text/javascript" src="js/scriptaculous/scriptaculous.js"></script> <script type="text/javascript" src="js/jayjax.js"></script> <script type="text/javascript" src="searcher.gjs"></script> <script type="text/javascript" src="all-beans.gjs"></script>
and implement the callback method from BookSearchView:
searcher.view.displayList = function(bookList) { jayjax.Dom.clear('books'); bookList.each(function(book){ var tr = " " + book.title + " " + book.author + " "; jayjax.Logging.debug(tr); new Insertion.Bottom('books', tr); }); }
Done. All the rest of devilish details can be found in the examples' war file that comes with the JayJax distribution.
You've bravely stayed the course through tons of code. I promise to entertain you with something much less implementation centric next time.
Johannes