I am attempting to design my first, super-simple GWT app, that takes advantages of most of GWT's major API features. I think I'm about 70 - 80% of the way there, but after pouring over the GWT docs, countless articles, and posting many other GWT-related questions here on SO, I am still having a tough time understanding the last 20 - 30% needed to put this app altogether.
I have called this first test app ClickItToWinIt, and I want it to look like this:
When the user clicks the "Win" button, a picture ("win-pic.png") pops up in the image frame on the left-hand side. When the user clicks the "Lose" button, a picture ("lose-pic.png") pops up in the same frame. The user can click back and forth between the buttons to make the different pictures display. This would be a single-page app, hosted locally on my machine, and would only need to contain 1 homepage, 1 module/entrypoint, etc.
Please note that the packaging/class structure proposed below is surely overkill for such a simple ClickItToWinIt app. However, before long I want to be moving on to bigger and better things with GWT, so it's important to me that I have an understanding of proper GWT coding before I start to tackle bigger apps with more complex UIs.
Also, the proposed structure below is based on 3 GWT principles that Google seems to encourage tirelessly:
Performance; client-side speed
Security
Separation of concerns (MVP, etc.) for ease of testing
One last item here: normally, in my PHP webdev days, I used the concept of "themes/skins" in some of my sites by deploying the site with a different CSS file that simply applied different styling rules to the same DOM elements. Thus I might have a "normal-styles.css" file that makes the site look "normal", but also have a "facebook-styles.css" file that gives the site the look-and-feel (colors, fonts, etc.) of Facebook, etc. I'd like to accomplish the same thing here and am proposing a net.bfodder.c2w.client.views.themes package that will have AbstractTheme subclasses in it. These subclasses would somehow be injected/baked into the view/presenter at build-time and would give me a way to deploy the app with a different theme or skin. I believe this is the right approach because (if my understanding of ClientBundle and CssResource is correct) GWT seems to have object-ified CSS styles into GWT POJOs. My AbstractTheme subclasses would somehow tie into CssResource and defined styles for all my Widgets.
So here is the proposed src/main/java structure of ClickItToWinIt (I'm developing in Eclipse 3.7 Indigo with the Google-Eclipse plugin):
ClickItToWinIt/
src/main/java/
net.bfodder.c2w
net.bfodder.c2w.client
MainModule (implements EntryPoint)
AppController
ClientFactory
net.bfodder.c2w.client.views
net.bfodder.c2w.client.views.ui
WinButton (extends Composite implements ClickHandler; hasA TextButton)
LoseButton (extends Composite implements ClickHandler; hasA TextButton)
ImageViewer (extends Composite; hasAn Image)
net.bfodder.c2w.client.views.containers
MainContainer
ButtonContainer
ImageContainer
net.bfodder.c2w.client.views.displays
WinActivity (extends AbstractActivity implements AcceptOneWidget)
LoseActivity (extends AbstractActivity implements AcceptOneWidget)
net.bfodder.c2w.client.views.themes
AbstractTheme
NormalTheme
FacebookTheme --> I really dont't care about FB, just using as an example of a well-known theme/skin
net.bfodder.c2w.client.presenters
IPresenter
ButtonPresenter (extends AbstractActivity implements IPresenter)
ImagePresenter (extends AbstractActivity implements IPresenter)
net.bfodder.c2w.client.history
InitialPlace (corresponds to http://localhost/clickittowinit)
WinPlace (corresponds to http://localhost/clickittowinit/#winning)
LosePlace (corresponds to http://localhost/clickittowinit/#losing)
net.bfodder.c2w.client.events
EventBus impl and GwtEvent impls
net.bfodder.c2w.server
Not worried about server-side for now; I think I "get" that much!
The AppController is for any oddball app-level business logic that doesn't belong to any one particular IPresenter subclass. The MainModule is where everything kicks off (DI, starting preliminary Activity, etc.). The buttons get placed inside ButtonContainer, the ImageViewer gets placed inside the ImageContainer, and both those inner containers get placed inside MainContainer (which I assume is created up in MainModule). As far as layout and style of these UI components, like I said this would be up to whatever the injected/configured AbstractTheme defines in its rule set.
I'm using the ClientFactory as recommended here for convenient access to major parts of the app's GWT plumbing.
As for the MVP "stuff", here's what I was thinking:
public class WinActivity extends AbstractActivity {
private final ClientFactory clientFactory;
private final WinPlace place;
public WinActivity(ClientFactory clientFactory, WinPlace place) {
this.clientFactory = clientFactory;
this.place = place;
}
#Override
public void start(AcceptsOneWidget panel, EventBus eventBus) {
ImagePresenter presenter = clientFactory.getImagePresenter();
// Inject the presenter with any stateful data here
// presenter.setImage(getWinImageUri());
presenter.go(panel);
}
}
The Question(s)!
Like I said up above, I believe I'm almost there, I'm just having a tough time bridging the gaps on some things. So I ask:
How do I wire up my AbstractTheme subclasses to use CssResource and ClientBundle so that my app gets injected/configured with the correct theme, and client browser download the correct CSS file (normal-style.css or facebook-style.css)?
Can someone properly explain the relationship between IPresenter (from classic MVP), AbstractActivity, "display regions" (AcceptsOneWidget) and Places? Is there a 1-to-1-to-1-to1 relation here, or is the intention with GWT to have, say, multiple display regions for every AbstractActivity, or some other set of ratios?
How do I connect the WinPlace with GWT's History API? So if the user clicks WinButton, LoseButton, WinButton, how to have that saved in browser history so they could hit the forward/back browser buttons and recreate this usage pattern over and over again?
When the WinButton gets clicked, it places a some click event on the Event Bus. Where and how do I wire up a handler/listener to the EventBus that will know: (a) to change the image in the ImageViewer, and (b) to store this state change in the History API?
I got the idea for the AppController from this article, which unfortunately never provides any code snippets for what the AppController might actually look like. Can anybody (who is familiar with the AppController pattern for GWT) shine some light as to what this would look like? Perhaps its somehow an IPresenter subclass with no particular Activity or view components?
In general, and I know that these kinds of "amidoinitrite?"-style questions are discouraged on SO, but I have to ask any battle-worn GWT veterans out there: am I way off-base here, or am I more or less on track with GWT best practices? Any suggestions?
I hate to ask such a "super-question" here, but I'd rather do this than clutter SO with 6 medium-sized questions, and just keep repeating the same problem setup over and over again. Plus, with a good code example, it's probably possible to answer all 6 in one fell swoop, so I took a chance here.
Thanks in advance.
Related
How should Listeners etc be managed? I've found only examples with one button etc.
I can think of following options:
Extra class for each - doesn't seem right, especially when items
can be created dynamically
Class for each group (such as form1,
form2, controlButtonsOnLeft, controButtonsOnRight, mainMenu,
userMenu, ...) where I'll check which button/component caused this
(via getSource method for example)
Some super (sized) controller,
which will accept all user actions
New anonymous class for each,
which will call controller's method with parameters specifying
details (probably enums)
And another question: I've found many examples for MVC, I was wondering what is better (or commonly used) for app. developed by 1 person (app will not be huge)?
A. Viewer sets listeners to controller (A1-3)
B. Controller calls viewer's methods, which accepts listener as parameter (methods addLoginSubmitListener, addControlBoldButtonListener etc)
All of above are possible to implement and so far I would choose B4.
Meaning in Control I would do something like this:
...
viewer.addLoginButtonListener(new Listener()
{
#Override
public void actionPerformed(ActionEvent e) {
...
someButtonsActionHandler(SomeButtonEnum, ActionEnum);
...
}
});
...
private void LoginActionHandler(LoginElementsEnum elem, ActionEnum action)
{
if (elem.equals(LOGINBUTTON)) {...}
...
}
...
This combines readable code (1 logic part at one place in code), doesnt create any unwanted redundant code, doesnt require any hardly-dynamic checks, is easily reusable and more.
Can you confirm/comment this solution?
To be honest the question comes down to a number of questions...
Do you want reusability?
Do you want configurability?
Are they self contained? That is, does it make sense for anybody else to listener to the component or need to modify the resulting action of the listener in the future?
Personally, I lean towards self containment. A single listener for a given action/task. This makes it easier to manage and change should I need to.
If I don't need reusability (of the listener) or configurability, then an anonymous inner class is generally a preferred choice. It hides the functionality and doesn't clutter the source code with small, once use classes. You should beware that it can make the source code difficult to read though. This of course assumes that the task is purpose built (its a single, isolated case). Normally, in these cases I will prefer to call other methods from the listener that actually do the work, this allows a certain amount of flexibility and extendability to the class. Too often you find yourself wanting to modify the behaviour of a component only to find that behaviour buried within an anonymous or private inner class...
If you want reusability and/or configurability - that is, the listener performs a common task which can be repeated throughout the program or over time via libraries, then you will need to provide dedicated classes for the task. Again, I'd favour a self contained solution, so any one listener does only one job, much easier to change a single listener then having to dig through a compound list of if-else statements :P
This could also be a series of abstract listeners, which can build functionality for like operations, deleting rows from a table for example...
You could considering something like the Action API (see How to Use Actions for more details), which are self contained units of work but which also carry configuration information with them. They are designed to work with buttons, such as JButtons and JMenuItems, but can also be used with key bindings, making them extremely versatile...
The second part of you question (about MVC) depends. I prefer to keep UI related functionality in the view and out of the controller as much as possible. Instead of allowing the controller to set listeners directly to components, I prefer to provide my own, dedicated, listener for the controller/view interaction, which notifies the controller of changes to the view that it might like to know about and visa versa.
Think about it this way. You might have a login controller and view, but the controller only cares about getting the credentials from the view and authenticating them when the view makes the request, it doesn't care how that request is made from the views perspective. This allows you to design different views for different circumstances, but so long as you maintain the contract between the view and the controller, it won't make any difference...But that's just me.
I'm creating my first "bigger" application in Java. As MVC is only pattern I know, I decided to use it. But there's something wrong with this concept.
For example. I need an Action (or generally event) fired from 2 places (from Button in frame and MenuItem). It has to do changes in at least 2 places and in the model.
I've got some ideas, but they seem wrong:
Pass the controller object to every view element, so newly created actions could use controller's methods to modify rest of the application.
Make controller static (for same reasons)
Make controller only model listener
Please tell me how to build it. Or give me some links to some easy to analyse applications.
Source of my project is here, if anyone wants to have a look: https://github.com/Arrvi/ColorExtractor
You are correct to use Action to encapsulate functionality for use by disparate components such as menus and buttons. A spectrum of examples is cited here. As regards MVC, recall that Swing uses a separable model architecture, examined here. In effect, the user is the controller, and not every interaction needs to pass through your application's controller.
If I understand correctly :
an Activity is a User action on widgets
This activity moves the application state in another Place
The url moves along, thanks to anchors (thought modern browsers have an api)
When we share the url, it define a Place, and it's enough to rebuild the State
(As I'm also a javascript guy, this looks much like Backbone's router and other modern JSFrameworks)
But to rebuild the State, we need to fetch some data to the Server. Is there anything in the P&A api to do this ? With RPC, this role is clearly done by GreetingServiceImpl that extends the RemoteServlet. With Backbone, we have the Sync object.
But I never see such code such when I look at A&P tutorials. Where is the Server ? Do we need RPC there ? Does it mix with RequestFactory ?
First, a small note about terminology:
A Place represents where you are in the app. When you look at that screen, it's generally composed of different "blocks", each dedicated to a specific activity, e.g.: a header (let's say with search box and logout link), a navigation menu, the "master" in a master-details view, the "details" in a master-details view. All these can be activities (though not necessarily, things that are never swapped to anything else won't gain anything being activities).
Because activities are by definition displayed on screen, you can interact with them, possibly triggering a move to another place (PlaceController#goTo).
The place is optionally synchronized with the URL (both ways) and generate browser history items; by default using the hash, but you can swap the implementation to use HTML5.
(places are similar to Backbone's router except they're type-checked, activities are a light layer on top with no equivalent in Backbone AFAICT)
Now to answer your question:
GWT is a toolkit, not a framework. That means most building blocks don't force you into using any other building block (places can work without activities, editors can work without widgets, etc.)
Activities start asynchronously, which is where you'd generally get the data from wherever it is. In the spirit of a toolkit, you're free to use whatever fits your needs: GWT-RPC, RequestFactory, RequestBuilder, Errai JAX-RS, Errai Bus, XMLHttpRequest, WebSockets, AppEngine Channels, etc. Some people also post events to their event bus to decouple the activity from how they get their data.
MVP describes the Client-architecture.
M_odel:
The business objects handled by you app.
V_iew:
UI elements, showing a representation of your model.
P_resenter:
A class which handles all userinteractions and modification to your model.
Lets assume you have an application which shows and stores Notes.
You have some Places:
a Place is like an good old HTML page in older days. In MVP it can be described a a set of running Presenter. In our simple application there are two places. Every Place does only have one running Presenter
NotesListPlace -> shows all stored notes
NotesEditPlace -> Creates / Edit a Note
The NotesEditPlace:
There is a View and a Presenter.
The View has an TextArea (for the Note) and a save button.
The presenter has a clickHandler for the save-button (there may be more, but as example it should be enough)
The User select a Note from the NoteList
PlaceChange from NoteListPlace -> NoteEditPlace
The Presenter starts and registers the click-handler at the view. If the button is pressed, the presenter reads the input from the textarea and update the Model (A new Notes-onject)
Now comes the server interaction. You can use every (GWT) transportlayer you want.
The success callback fires a PlaceChange event to the NoteListPlace.
All starts again. The presenter starts, a new server interacction to load the MOdel ( A List of Notes). The view is updated by the presenter...
Update 1
There is no need of a server. The presenter may persist the Model to the localStorage of the browser.
Update 2
You can use every transport mechanism you want. RequestFactory, GWT-RPC. I use RequestBuilder and GWT AutoBeans.
I have been asked to revamp an existing JDialog that is a child container of an in-house Swing app. I will be re-writing the dialog from scratch and have been asked to lead the charge towards making the Swing app resemble a true MVC/MVP architecture (so my JDialog revamp will be the first of many pro-MVC changes to the app itself).
I understand MVC/MVP as it pertains to web apps:
Controller - is what the web app framework dispatches to handle HTTP requests; typically consists of multiple methods, where each "controller method" handles the request for a slightly different URL
Model - the DAO or POJO/bean representing call-specific data; controller fetches the Model from the DB and injects it into the View
View - the mechanism that ultimately produces HTML/JSP that will be sent back to the client/requester
This is not how all MVC/MVP web frameworks operate, but is the general idea.
But I'm struggling trying to determine how to translate this to a Swing app. In the Swing app, you have:
The JDialog itself
All the UI widgets (JButtons, JTextFields, etc.) that make up the "view" of the dialog
The action/event listeners for all the UI widgets which collectively make up the "business logic" for how the dialog will operate when the user interacts with the view
All the other "UI glue code" (setting which widgets will be enabled/disabled, setting their sizes and positions on screen, setting their tooltip texts, etc.)
Plus a lot of other stuff
So I ask: how do I organize all the code necessary for a functioning JDialog using an MVC/MVP architectural pattern? Also, if there are any articles, tutorials, or existing open souce projects that showcase MVC/MVP Swing apps, I am interested in them as well. Thanks in advance!
As discussed here, Swing MVC hinges on the observer pattern used to propagate model changes back to any listening view(s). As a result, much depends on the components in your JDialog. If your dialog must be modeless, the examples here and here may be helpful.
Since there are many valid recipes out there, I'll only discuss what I use: a modified MVP design which also borrows ideas from The Humble Dialog Box.
Basically, create your GUI with as little application logic as possible (zero is the goal). Create "presenter" classes (similar to Controllers) that have a handle to the GUI and inject the appropriate listeners onto the UI.
Some benefits:
Since all application code is out of the UI, your code is now 100% testable.
You can quickly prototype your GUI without having to launch your app everytime, which can be a big time-saver.
Separation of concerns makes code easier to read/maintain.
Your GUI code will be Swing only. A new team member who isn't familiar with your app but is familiar with Swing can jump right in.
With regard to Swing's implementation of MVC, we actually don't care. That's Swing's business. We assume Swing works (which it usually does). True, we need to know these sorts of things for writing custom renders, editors, models, etc., but those are details that the application framework (which is what I think you're asking about) doesn't need to know or care about, for the most part.
I would do like this:
MyModel model = engine.getDataFromDatabase();
myController.displayDataOnMyCustomView(myPresenter, model);
And at controller side, probably will remove a lot of listeners, set the data based on model, set sizes, locations and any other state representing stuff and finally re-add the listeners.
The myPresenter should be a custom JDialog with various basic ui elements (Component)on his UI tree.
I want to create a game that will work both locally and online.
My first thought was to create an interface that would have all the methods that will be needed by the GUI for the business logic and then have a network implementation and a local implementation.
This works fine for request-response messages. But what about messages that the server sends, where I have to update some GUI components (i.e. JLabels)?
My first solution to this was to implement listeners, where each change in the implementation will fire an event. The GUI would register and change it's components appropriately. However, calls to fire events in the business logic looks a little wrong.
Am I in the right track? Because I think I'm not. Any suggestions?
Thank you.
NOTE: The client is a simple Java Swing GUI.
What you have described will serve the goal of keeping the model independent of presentation issues, which is A Good Thing. This will also help you during design, development, and maintenance of the model, because you can write unit tests on the basis that certain changes in the model should fire specific events, without worrying about what that might look like on a screen.
And, of course, it frees you up to have different GUI designs for different environments.
The key is that the events should be about changes in the state of the model, and not about intended actions/representations at the presentation level. Let the presentation layer deal with whether/how to respond to a model event.
I'll admit that I do web development, so I don't have much experience with Swing.
But I've always thought that the way I'd approach it would be to break the app into packages /view, /model, and /controller. The relationships would be unidirectional: /controller would know about both /model and /view, but neither would import any classes from /controller or each other.
The /view layer components would never be JFrames; they'd always be JPanel or another suitable container that could be composed together into JFrames as needed. Each would have references to Listener interfaces, initialized in constructors, and would defer to these for event handling:
public class ExamplePanel extends JPanel implements ActionListener
{
private JButton button;
private ActionListener buttonListener;
public ExamplePanel(ActionListener buttonListener)
{
this.button = new JButton("Do Something");
this.buttonListener = buttonListener;
this.button.addListener(this.buttonListener);
}
public void actionPerformed(ActionEvent e)
{
this.buttonListener.actionPerformed(e);
}
}
This arrangement works well with dependency injection, because now the controller can choose to use a local or remote implementation of that Listener interface, changing the behavior in a way that doesn't affect the client at all.
I'll admit that I've never followed it all the way through.
The Spring folks have a rich Swing client module, but it appears to have fallen out of favor. It looks like they've decided that a BlazeDS direction is a better choice for rich clients. But perhaps you can glean some design ideas from their approach.