tag:blogger.com,1999:blog-61426860528215953872024-02-28T06:48:41.950+01:00Yennick TrevelsMay the code be with youYennick Trevelshttp://www.blogger.com/profile/13084772261005156419noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-6142686052821595387.post-90006676517988551342013-10-16T23:28:00.001+02:002021-05-20T10:32:04.429+02:00Blog movedHi,
You can find my new space on <a href="https://digitalbuff.dev">digitalbuff.dev</a> where I share my 15+ years in software development and coaching.
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWOGb9JlU721utGO9PoeUXn0AeY_xNGR9VXim1qKe2gn0Z9M753mD2dlflBMnnYkXR3tpUwSfI3g0bpolQ8px3hkXwgYfsqdm5GBlMEeeph_Qz9Y3_5Wo4qrNkFuo24YZyUBjQb82JQ6AB/s903/digitalbuff-banner.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="345" data-original-width="903" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWOGb9JlU721utGO9PoeUXn0AeY_xNGR9VXim1qKe2gn0Z9M753mD2dlflBMnnYkXR3tpUwSfI3g0bpolQ8px3hkXwgYfsqdm5GBlMEeeph_Qz9Y3_5Wo4qrNkFuo24YZyUBjQb82JQ6AB/s600/digitalbuff-banner.jpg"/></a></div>Yennick Trevelshttp://www.blogger.com/profile/13084772261005156419noreply@blogger.com0tag:blogger.com,1999:blog-6142686052821595387.post-13131293915316383412013-03-22T14:15:00.001+01:002021-05-20T10:33:21.784+02:00JavaFx: Structuring your Application - Service and Application State layerThis post is part of a series of blog posts about structuring your JavaFx application. Here's an overview:
<ol>
<li><a href="http://jedicoder.blogspot.be/2013/03/javafx-structuring-your-application.html">Overview</a></li>
<li><a href="http://jedicoder.blogspot.be/2013/03/javafx-structuring-your-application_11.html">View layer</a></li>
<li><a href="http://jedicoder.blogspot.com/2013/03/javafx-structuring-your-application_18.html">Application logic layer</a></li>
<li>Service - Application State layer(this post)</li>
</ol>
In this post I'll explain which classes should be used to communicate with external sources and how we store application state.
<br />
<br />
<h1>Service</h1>
A Service is used to communicate with an external resource. This can be anything, from a webserver to a printer. <br />
Every Service should focus on a certain resource or a subset of it (like a Service which only performs contact related REST calls).<br />
Again, it's also important to put your Service behind an interface. By doing this you can mock it when unit testing commands, but it also allows you to create a stub implementation which you can use while the back-end developers are creating the server code and swap it with the real implementation once they have finished the backend code.
<br />
<br />
Such a service can look like this:
<pre class="brush:java">
public interface IEventService {
List<EventVO> getEvents();
EventVO getEventDetails(String id);
void acceptEvent(EventVO event);
void declineEvent(EventVO event, String reason);
}
</pre>
And the stub implementation:
<pre class="brush:java">
public class StubEventService implements IEventService {
private List<EventVO> events;
public StubEventService() {
Calendar calendarDate = GregorianCalendar.getInstance();
calendarDate.set(2012, 4, 24, 10, 20);
Date date = calendarDate.getTime();
events = new ArrayList<EventVO>();
events.add(createEvent("1", "First Event", "Paris, France", date, date,
"The event will showcase the first application"));
events.add(createEvent("2", "Special meeting", "Manchester, UK", date, date,
"A special meeting for a special application"));
events.add(createEvent("3", "Technology meetup", "Brussels, Belgium", date, date,
"Geeking out with the latest technologies"));
events.add(createEvent("4", "Designer Conference", "Boston, US", date, date,
"Various talks by the most famous designers in the industry"));
}
@Override
public List<EventVO> getEvents() {
return events;
}
@Override
public EventVO getEventDetails(String id) {
for (EventVO event : events) {
if(event.getId() == id) {
return event;
}
}
return null;
}
@Override
public void acceptEvent(EventVO event) {
}
@Override
public void declineEvent(EventVO event, String reason) {
}
private EventVO createEvent(String id, String name, String location, Date startTime, Date endTime, String description) {
EventVO event = new EventVO();
event.setId(id);
event.setName(name);
event.setLocation(location);
event.setStartTime(startTime);
event.setEndTime(endTime);
event.setDescription(description);
return event;
}
}
</pre>
<h1>The Model</h1>
A model is used to store and share state across your application. This allows you to react to certain state changes in multiple parts of your application.<br />
A model is in most cases just a class with some properties that define the state (e.g. the selected contact, the list of contacts that is shown). In some cases it can contain some basic logic, but this should never be complicated (if it is, then move it to a command). <br />
In most cases it will be a command that updates the model or takes values from it to return it to the view layer.<br />
As always, you should put the Model behind an interface for unit testing purposes.
<br />
<br />
This is how such a model can look like:
<pre class="brush:java">
public interface IEventSelectionModel {
EventVO getSelectedEvent();
void setSelectedEvent(EventVO event);
ObjectProperty<EventVO> getSelectedEventProperty();
}
</pre>
<br />
And the implementation:
<pre class="brush:java">
public class EventSelectionModel implements IEventSelectionModel {
private ObjectProperty<EventVO> selectedEvent = new SimpleObjectProperty<EventVO>(this, "selectedEvent");
@Override
public EventVO getSelectedEvent() {
return selectedEvent.get();
}
@Override
public void setSelectedEvent(EventVO event) {
selectedEvent.set(event);
}
@Override
public ObjectProperty<EventVO> getSelectedEventProperty() {
return selectedEvent;
}
}
</pre>
<h1>Conclusion</h1>
This was the final article in the series. <br />
My goal was to share my view on a fat client architecture and hopefully get the conversation started about client architectures with JavaFx. That way we can improve this architecture or even find (better) alternatives.Yennick Trevelshttp://www.blogger.com/profile/13084772261005156419noreply@blogger.com2tag:blogger.com,1999:blog-6142686052821595387.post-89092972051823677692013-03-18T13:49:00.001+01:002021-05-20T10:33:31.673+02:00JavaFx: Structuring your Application - Application Logic LayerThis post is part of a series of blog posts about structuring your JavaFx application. Here's an overview:
<ol>
<li><a href="http://jedicoder.blogspot.be/2013/03/javafx-structuring-your-application.html">Overview</a></li>
<li><a href="http://jedicoder.blogspot.be/2013/03/javafx-structuring-your-application_11.html">View layer</a></li>
<li>Application logic layer(this post)</li>
<li><a href="http://jedicoder.blogspot.com/2013/03/javafx-structuring-your-application_22.html">Service - Application State layer</a></li>
</ol>
Because this architecture is targeting fat clients which have all the business logic on the client side it is important to structure this in an organized and efficient way. In this post I'll explain how you can organize your application logic in a way that it won't block the UI.
<br />
<br />
<h1>The Command</h1>
A command is a stateless object which is executed once and then disposed of. It has a single responsibility, which clearly defines its purpose.<br />
Such a command can for example have the responsibility to create a new contact, calculate the total amount of money a client has to pay etc.<br />
This leads to a higher number of classes, but it has some advantages over a controller:
<ul>
<li>A command will have less dependencies because of its single responsibility. This makes it easier to test.</li>
<li>When using good class/package name conventions it's easier to find a certain piece of logic.</li>
</ul>
A command can use Services and Models to do its job, but should never reference the mediator.
<br />
<h2>Running it in the background</h2>
Because business logic should run in a background thread to avoid blocking the UI, I'm using a convention to make every command extend from the JavaFx Service class. <br />
The Service class is used in JavaFx to run some code in one or more background threads. More info on this class can be found here: <a href="http://docs.oracle.com/javafx/2/api/javafx/concurrent/Service.html">http://docs.oracle.com/javafx/2/api/javafx/concurrent/Service.html</a> <br />
This fits perfectly in my design because it makes sure that all business logic is executed in a background thread. Because it's an integral part of our application structure developers won't forget to start a new thread because it will be done transparently when creating a new instance of a command and starting it.
<br />
<br />
<h2>How it looks like in code</h2>
This is how it looks like in code. The command has one parameter which should be set before starting the command and it has a dependency to the IEventService. When it's finished it return an EventVO instance with all the details of the event.
<pre class="brush:java">
public class LoadEventDetailsCommand extends Service<EventVO> {
@Inject
public IEventService eventService;
public String eventId;
@Override
protected Task<EventVO> createTask() {
return new Task<EventVO>() {
@Override
protected EventVO call() throws Exception {
return eventService.getEventDetails(eventId);
}
};
}
}
</pre>
<br />
And this is how you can use it in the mediator. The commandProvider is something which I'll discuss in a moment, but it basically creates a new instance of a certain command class. When you call the start() method the command will start its execution in a background thread.
<pre class="brush:java">
LoadEventDetailsCommand command = commandProvider.get(LoadEventDetailsCommand.class);
command.setOnSucceeded(new LoadEventDetailsSucceededHandler());
command.eventId = eventSelectionModel.getSelectedEvent().getId();
command.start();
</pre>
<br />
And finally the succeeded handler which is just an inner class in my mediator. It gets the EventVO result from the command and asks the view to show the new details:
<pre class="brush:java">
private class LoadEventDetailsSucceededHandler implements EventHandler<WorkerStateEvent> {
@Override
public void handle(WorkerStateEvent workerStateEvent) {
view.updateEventDetails((EventVO) workerStateEvent.getSource().getValue());
}
}
</pre>
<h1>The CommandProvider</h1>
The CommandProvider is a class which I've created as sort of a Command factory, which uses a Guice injector to produce the instances. This allows us to inject dependencies in the commands.
<br />
<br />
The interface:
<pre class="brush:java">
public interface ICommandProvider {
<T extends Service> T get(Class<T> type);
}
</pre>
<br />
And the implementation:
<pre class="brush:java">
public class CommandProvider implements ICommandProvider {
@Inject
public Injector injector;
public <T extends Service> T get(Class<T> type) {
return injector.getInstance(type);
}
}
</pre>
<h1>Conclusion</h1>
In this article we've seen how you can organize the business logic in a single layer and how you can make sure that it won't block the UI. In my next and final article I'll explore the Service and Model classes which allow us to communicate with external sources and store application state.Yennick Trevelshttp://www.blogger.com/profile/13084772261005156419noreply@blogger.com1tag:blogger.com,1999:blog-6142686052821595387.post-30088660140782140392013-03-11T13:21:00.001+01:002021-05-20T10:33:39.352+02:00JavaFx: Structuring your Application - View LayerThis post is part of a series of blog posts about structuring your JavaFx application. Here's an overview:
<ol>
<li><a href="http://jedicoder.blogspot.be/2013/03/javafx-structuring-your-application.html">Overview</a></li>
<li>View layer (this post)</li>
<li><a href="http://jedicoder.blogspot.com/2013/03/javafx-structuring-your-application_18.html">Application logic layer</a></li>
<li><a href="http://jedicoder.blogspot.com/2013/03/javafx-structuring-your-application_22.html">Service - Application State layer</a></li>
</ol>
In this post I'll explain the components of the view layer (View and Mediator), how they should interact and some best practices on how to use them.
<br />
<br />
<h1>The View</h1>
This class is where you'll use the JavaFx components to build your UI. It's also responsible for displaying notifications, opening new windows or just about anything that it related to the UI (and which should happen on the UI thread).<br />
I prefer to create my UI with pure Java code instead of using FXML. It's fast, easier to use with Guice and it's giving me more control over my code. Therefore my structure is based on this.<br />
To keep the Views focused on their tasks, you should follow these rules.
<br />
<br />
<h2>Rule 1: Don't let your View extend JavaFx components</h2>
The View should never extend a JavaFx component, it should only use JavaFx components. This rule is also known as "composition over inheritance". <br />
Our View classes will have a getView() method which will create and return the top-level component/container of that view. That way the actual view is only instantiated when the getView() method is called. This has several benefits:
<ol>
<li>Remember from the previous post, the View classes are mapped in Guice and injected in the View classes where they will be used. By not extending a JavaFx component, the cost of creation will be lower when Guice creates and injects these Views. </li>
<li>You can extend any other class you want because the design doesn't force you to extend JavaFx components.</li>
<li>The API of your view will not be cluttered with all the methods of the JavaFx component</li>
</ol>
<h2>Rule 2: The View should never contain application logic</h2>
The view can contain view logic (like when to play an animation), but should never contain application logic. <br />
Application logic can sometimes take up several 100ms. If you do this on the UI thread, then during this time the UI will not be able to update anything, so it will feel unresponsive. Therefore it's very important to run your application logic on a separate thread (which in this structure will be in a Command).<br />
If some application logic should be executed in response to a button click, it should call the mediator to delegate this to the application logic layer.
<h2>Rule 3: Put your view behind an interface </h2>
You should create an interface for your View class. This interface should contain the methods that can be called by the Mediator. <br />
Creating such an interface has several advantages:
<ol>
<li>You create an API for your View which clearly indicates what it can do.</li>
<li>The mediator can work against this API, so it isn't tied to a certain View implementation. This is especially handy when writing unit tests for your mediator because you can create a mock for the view and inject that into the mediator.</li>
</ol>
<h2>How it looks like in code</h2>
Now how does this look like in code when you apply the rules above? I'll show you some code of a view which shows a list of events. The user can select one of the events by clicking on them.
<br />
<br />
First we have the View interface:
<pre class="brush:java">
public interface IEventListView {
/**
* Asks the view to update the list of events with this new list.
*/
void updateEventList(List<EventVO> events);
}
</pre>
And then we have the View implementation:
<pre class="brush:java">
public class EventListView implements IEventListView {
@Inject
public IEventListMediator mediator;
private ListView listView;
private ObservableList events;
public ListView getView() {
if(listView == null) {
events = FXCollections.observableArrayList();
listView = ListViewBuilder.create()
.items(events)
.onMouseClicked(new EventListMouseClickedHandler())
.build();
listView.setCellFactory(new EventListItemRenderer());
//when the view is created, ask the mediator to load the events.
mediator.loadEvents();
}
return listView;
}
@Override
public void updateEventList(List<EventVO> events) {
this.events.clear();
this.events.addAll(events);
}
private class EventListMouseClickedHandler implements EventHandler<MouseEvent> {
@Override
public void handle(MouseEvent mouseEvent) {
mediator.updateSelectedEvent((EventVO)listView.getSelectionModel().getSelectedItem());
}
}
}
</pre>
This view can then be used in the overview View like this:
<pre class="brush:java">
public class EventOverviewView implements IEventOverviewView {
...
@Inject
public EventListView eventListView;
public Pane getView() {
if(view == null) {
view = PaneBuilder.create()
.children(
eventList = eventListView.getView()
)
.build();
...
}
return view;
}
...
}
</pre>
<br />
<br />
<h1>The Mediator</h1>
The Mediator is the postman between the view and the application logic. It is receiving messages (calls) from the View and it passes them on to Commands. It also passes on messages that are coming from the application logic to the view. Again, some rules apply here.
<br />
<br />
<h2>Rule 1: The mediator should not contain any application logic</h2>
The mediator runs on the UI thread, so it should not contain any application logic as this can make your application unresponsive. It should instead create a command (by using the CommandProvider class) and start the command which will then execute the application logic.<br />
By following this rule we avoid duplicate code and make sure that application logic can always be found in one layer instead of being scattered in multiple layers, which in the end makes your application more maintainable.
<h2>Rule 2: The mediator should have an interface</h2>
The Mediator should have an interface which defines which actions it can perform. These methods can then be called in the view.
<h2>Rule 3: Don't do complex manipulations on your Models in your mediator</h2>
In some cases it can be handy to inject a Model into the mediator to directly access the application state without having to write a command for it. But to avoid excessive use of this, you should only listen to changes on the model, get simple data from it or set simple things on it. If the data needs to be manipulated in any way, don't access the model directly but create a command instead which will contain this logic. So be very careful when accessing the Model from your Mediator.
<br />
<br />
<h2>How it looks like in code</h2>
When you apply these rules it will look like this.
<br />
<br />
First we have the mediator:
<pre class="brush:java">
public interface IEventListMediator {
void loadEvents();
void updateSelectedEvent(EventVO event);
}
</pre>
And then we have the Mediator implementation:
<pre class="brush:java">
public class EventListMediator implements IEventListMediator {
@Inject
public ICommandProvider commandProvider;
@Inject
public IEventSelectionModel eventSelectionModel;
@Inject
public IEventListView view;
public void loadEvents() {
LoadEventsCommand command = commandProvider.get(LoadEventsCommand.class);
command.setOnSucceeded(new LoadEventsSucceedHandler());
command.start();
}
@Override
public void updateSelectedEvent(EventVO event) {
eventSelectionModel.setSelectedEvent(event);
}
private class LoadEventsSucceedHandler implements EventHandler<WorkerStateEvent> {
@Override
public void handle(WorkerStateEvent workerStateEvent) {
view.updateEventList((List<EventVO>)workerStateEvent.getSource().getValue());
}
}
}
</pre>
<h1>Conclusion</h1>
In this post we've covered the View layer and the rules that should be followed. It also showed how the View and the Mediator communicate with each other. In the next post I'll cover the application logic layer were we'll see how heavy application logic will be offloaded to a separate thread in a consistent way.Yennick Trevelshttp://www.blogger.com/profile/13084772261005156419noreply@blogger.com7tag:blogger.com,1999:blog-6142686052821595387.post-77709877167252390982013-03-07T21:20:00.001+01:002021-05-20T10:33:48.191+02:00JavaFx: Structuring your Application - Overview<h1>Introduction</h1>
JavaFx is a new rich client framework by Oracle. It allows you to create visually pleasing enterprise business applications with the Java language.
<br /> <br />
While many small demos are showing up in the community, there aren't many articles on how to structure your JavaFx application. Using a good structure makes it easier to maintain your application, add new features and improves overall stability. These are all very important in enterprise applications.<br />
This serie of articles will try to remedy that by showing you one of many ways to structure your application. This is certainly not the only way to do it, but it will give you a starting point. Even this structure is open for improvement (as every structure is).
<br /> <br />
This serie will consist of four blog posts:
<ol>
<li>Overview (this blog post)</li>
<li><a href="http://jedicoder.blogspot.com/2013/03/javafx-structuring-your-application_11.html">View layer</a></li>
<li><a href="http://jedicoder.blogspot.com/2013/03/javafx-structuring-your-application_18.html">Application logic layer</a></li>
<li><a href="http://jedicoder.blogspot.com/2013/03/javafx-structuring-your-application_22.html">Service - Application State layer</a></li>
</ol>
<h1>High-level Overview</h1>
The structure I will describe is based on Robotlegs, an Apache Flex micro-architecture library. But instead of using events to decouple the layers, I went with for direct calls (with interfaces in-between). While events allow you to decouple the layers even more, I prefer direct calls with interfaces over events because they make it easier to follow the flow of your application.
<br /><br />
The diagram below shows the different components and layers in my architecture. The arrows indicate the dependencies.
<br /><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQLPypjRoUvtfmBfFQrmOcsz9umFyBTzK90ml0gvwRyjlavOIzXdjsmkRmv0nW-yq0dh0IQtjppOLUWz_CsjHwpA2lBi_0xJo5vWpNK8i6wP_hyphenhyphenSxi0C-zXr-1F8oIj4NOtSoR-NdTccC8/s1600/structure-overview.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQLPypjRoUvtfmBfFQrmOcsz9umFyBTzK90ml0gvwRyjlavOIzXdjsmkRmv0nW-yq0dh0IQtjppOLUWz_CsjHwpA2lBi_0xJo5vWpNK8i6wP_hyphenhyphenSxi0C-zXr-1F8oIj4NOtSoR-NdTccC8/s320/structure-overview.png" /></a>
<br /><br />
<dl style="list-style-type: none;">
<li><b>View:</b> This is where the JavaFx components are used to build the UI.</li>
<li><b>Mediator:</b> The mediator facilitates the communication between the view and the application logic layer. This is why it's both included in the view layer as the application logic layer. This layer should not contain application logic, it's just a postman who receives calls from the view and delegates them to the application logic layer and vise versa.</li>
<li><b>Command:</b> This is where your application logic will reside. A Command is a class which executes a single unit of work and will be disposed when it's finished.</li>
<li><b>Service:</b> A service is used to access external resources. This can be a remote service, a file on the filesystem or a device attached to the user's pc.</li>
<li><b>Model:</b> A model stores the state of your application. This can be the selected record which should be accessible in multiple views.</li>
</dl>
<br />
The diagram below shows a sample flow of an application. In this case the user clicked on a button to delete a contact in a list.
<br /><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4QT0C4E-n3nXhuT-bGAmYhIyTxZfz4_JkaqiBwHHvERjqdtj205lIbhNx5Y0e_u5ZuicamSyL3MqQvU32EcfNNHfbuXF2DNkkXJW3jmrxvUA4mem4PRJifrTfDV7LdxnWaH8Lf_W71rN6/s1600/structure-flow.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4QT0C4E-n3nXhuT-bGAmYhIyTxZfz4_JkaqiBwHHvERjqdtj205lIbhNx5Y0e_u5ZuicamSyL3MqQvU32EcfNNHfbuXF2DNkkXJW3jmrxvUA4mem4PRJifrTfDV7LdxnWaH8Lf_W71rN6/s320/structure-flow.png" /></a>
<br />
<br />
<ol>
<li>The view asks the mediator to delete the item by calling the deleteContact(contact) method on the IContactListMediator interface.</li>
<li>The mediator creates a new DeleteContactCommand and registers a success handler on it. Then it calls the start() method on the command.</li>
<li>The command calls the contact service to delete the contact from the database</li>
<li>The command calls a method on the model to remove the contact from the application state. It receives the updated list of contacts from the model</li>
<li>The command finishes and triggers the registered success listeners. It provides the updated list of contacts to the success handlers.</li>
<li>The success handler in the mediator asks the view to update the list of contacts based on the updated contact list it got from the command.</li>
</ol>
<h1>Used libraries</h1>
For my application I didn't use any framework (except for JavaFx, obviously), I wanted to create my own structure without the overhead of a framework. All I used was the JavaFx framework and Guice for dependency injection. <br />
For those interested in build tools, I used the JavaFx Gradle plugin created by Danno Ferrin to create a build script.
<h1>Dependency Injection</h1>
<h2>Mapping your dependencies</h2>
A DI library like Guice allows you to inject instances of certain classes into other classes without you having to manually instantiate and inject them. This can greatly improve the quality of your code since you don't have to write all that yourself. Guice is basically the glue that holds your application together.
<br /><br />
In Guice you have to create a Module class which defines all the mappings. Such a module class can look like this for a simple application:
<pre class="brush:java">
public class EventManagerModule extends AbstractModule {
@Override
protected void configure() {
bind(EventManagerModule.class).toInstance(this);
mapViews();
mapMediators();
mapCommands();
mapServices();
mapModels();
mapInfrastructure();
}
private void mapViews() {
bind(IEventOverviewView.class).to(EventOverviewView.class);
bind(IEventListView.class).to(EventListView.class);
bind(IEventDetailView.class).to(EventDetailView.class);
}
private void mapMediators() {
bind(IEventOverviewMediator.class).to(EventOverviewMediator.class);
bind(IEventListMediator.class).to(EventListMediator.class);
bind(IEventDetailMediator.class).to(EventDetailMediator.class);
}
private void mapCommands() {
bind(ICommandProvider.class).to(CommandProvider);
bind(LoadEventsCommand.class);
bind(AcceptEventCommand.class);
bind(DeclineEventCommand.class);
}
private void mapServices() {
bind(IEventService.class).to(StubEventService.class);
}
private void mapModels() {
bind(IEventSelectionModel.class).to(EventSelectionModel.class).in(Singleton.class);
}
private void mapInfrastructure() {
bind(ITranslationProvider.class).to(ResourceBundleTranslationProvider.class).in(Singleton.class);
}
}
</pre>
So in most cases you will be mapping implementations to interfaces. Always try to use interfaces. This allows you to, for example, create a stub implementation of a service (in this case StubEventService) and a real implementation which you can then just swap by changing the Guice mapping.<br />
Only for the Commands I didn't create interfaces because they wouldn't add that much value. They would all practically be marker services, but you'll see that in my following posts.
<br /><br />
While this Module implementation is ok for a small application, it can quickly explode in one huge class when you're building a bigger application. This is where bootstrap classes come in handy. A bootstrap class is just a class which initializes a certain part of your application. In this case it would initialize the mappings of the views, the mediators or the commands. Such a bootstrap class would look like this:
<pre class="brush:java">
public class MediatorMapper implements Mapper {
private AbstractModule module;
public MediatorMapper(AbstractModule module) {
this.module = module;
}
public void bootstrap() {
module.bind(IEventOverviewMediator.class).to(EventOverviewMediator.class);
module.bind(IEventListMediator.class).to(EventListMediator.class);
module.bind(IEventDetailMediator.class).to(EventDetailMediator.class);
}
}
</pre>
Your module would then look like this:
<pre class="brush:java">
public class EventManagerModule extends AbstractModule {
@Override
protected void configure() {
bind(EventManagerModule.class).toInstance(this)
new ViewMapper(this).bootstrap();
new MediatorMapper(this).bootstrap();
new CommandMapper(this).bootstrap();
new ServiceMapper(this).bootstrap();
new ModelMapper(this).bootstrap();
new ModelMapper(this).bootstrap();
}
}
</pre>
<br />
<h2>Wiring it all together</h2>
Now how do you wire all this together? Well, that is what I'm going to show you now.
<br />
<br />
In your Main class you will create a Guice Injector and with this injector you will instantiate the main view of your application.
Your Main class will look like this:
<pre class="brush:java">
public class Main extends Application {
public static void main(String[] args) {
Application.launch();
}
@Override
public void start(Stage stage) throws Exception {
Injector injector = Guice.createInjector(new EventManagerModule());
EventOverviewView eventOverviewView = injector.getInstance(EventOverviewView.class);
Scene scene = SceneBuilder.create()
.root(
eventOverviewView.getView()
).width(900)
.height(700)
.build();
scene.getStylesheets().add(Main.class.getResource("/EventManager.css").toExternalForm());
stage.setScene(scene);
stage.show();
}
}
</pre>
The views that are being used in the main view are also injected in the main view. Also, the mediator that is behind the main view is also injected. This patterns is used for every view.
<pre class="brush:java">
public class EventOverviewView implements IEventOverviewView {
@Inject
public IEventOverviewMediator mediator;
@Inject
public EventListView eventListView;
@Inject
public EventDetailView eventDetailView;
...
}
</pre>
Then, in the mediator, we inject the view and the commandProvider (this is a class which allows to create command instances on the fly).
<pre class="brush:java">
public class EventOverviewMediator implements IEventOverviewMediator {
@Inject
public IEventOverviewView view;
@Inject
public CommandProvider commandProvider;
...
}
</pre>
And in the application logic layer we inject the service/model in the command.
<pre class="brush:java">
public class LoadEventsCommand extends Service<List<EventVO>> {
@Inject
public IEventService eventService;
...
}
</pre>
<h1>Conclusion</h1>
In this post I gave a broad overview of the structure and explained how dependency injection fits into this. <br />
In the following posts I will go into more detail for each layer and give some best practices. <br />
You can find the full sample application here: <a href="https://github.com/SlevinBE/JavaFx-structure-demo">https://github.com/SlevinBE/JavaFx-structure-demo</a>Yennick Trevelshttp://www.blogger.com/profile/13084772261005156419noreply@blogger.com29tag:blogger.com,1999:blog-6142686052821595387.post-1864535895773155422012-03-28T23:45:00.000+02:002012-03-28T23:45:09.687+02:00GradleFx: What's to come (short term)In this post I'll give you an overview of the upcoming changes (short term) in GradleFx. As you'll notice the focus will be on improving what's already in GradleFx.
<br /><br />
<h2>Next GradleFx release</h2>
So let's get started with the next release which is right around the corner. The two biggest changes will be:
<ul>
<li>Better error and warning messages.</li>
<li>Big improvements to the FlexUnit integration.</li>
</ul>
<br />
<h3>Better error and warning messages</h3>
Did you also got that nasty error when you didn't specify the FLEX_HOME environment variable when you first ran a GradleFx project? Well, you won't get that one anymore in the next version of GradleFx, including some other checks which will produce some more meaningful error and warning messages, like when you use a compiler property which is also being used by GradleFx.
<br /><br />
<h3>FlexUnit improvements</h3>
Some major changes have been made to the FlexUnit integration. The configuration process has been greatly simplified. This is what you won't have to do anymore:
<ul>
<li><s>Manually download FlexUnit</s></li>
<li><s>Specify the name of the FlexUnit ant task</s></li>
<li><s>Create a FlexUnit Runner mxml class</s></li>
<li><s>Update the test cases in the FlexUnit Runner</s></li>
</ul>
These are now improved as follows:
<ul>
<li>You have to define the FlexUnit ant task as a maven dependency (the artifact should be on Maven Central shortly), so no need anymore to manually download FlexUnit.</li>
<li>The FlexRunner is now created automatically</li>
<li>GradleFx will scan for classes ending with Test.as in your test source folder. This pattern can be changed by overriding the flexunit.includes and flexunit.excludes properties</li>
</ul>
So these changes greatly reduce the required configuration, which brings the FlexUnit integration to a quality level.
<br /><br />
<h2>What will come after the upcoming GradleFx version?</h2>
The features that will be implemented after this upcoming GradleFx release will revolve around automatically downloading the Flex SDK and Flash executable (used for the unit tests). This is the last step to make a GradleFx build stand on its own without needing initial configuration by the end-user.
<br /><br />
<h3>Automatic download of the Flex SDK</h3>
Right now you have to create a FLEX_HOME environment variable or specify the flexHome property which point to the Flex SDK installed on your machine.
I want to improve this process by automatically downloading the Flex SDK and unzipping it to a directory which can be accessed by GradleFx. Now, how will this work?
I've got the following idea in mind:
Create a flexSdkUrl property to which you can specify the url to a Flex SDK zipfile, which you can specify like this:<br/>
<pre class="brush:groovy">
flexSdkUrl = 'http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4.5/flex_sdk_4.5.1.21328A.zip'
</pre>
This will then download the Flex SDK, unzip it to a %USER_HOME%/gradlefx/sdks/flexsdk-x.x folder (which will be configurable) and which will be used by GradleFx to run the compiler etc.<br />
Again a great improvement which follows the KISS principle (Keep It Simple, Stupid). This should allow a great deal of flexibility in which SDK you use and where you host it. You can even create your own custom SDK (e.g. with a different AIR version in it) and link to it.
<br /><br />
<h3>Automatic download of the Flash executable</h3>
This will follow the same principle as the SDK download.
You will be able to specify the Flash executable download url like this:
<pre class="brush:groovy">
flashExecutableUrl = 'http://download.macromedia.com/pub/flashplayer/updaters/10/flashplayer_10_sa_debug.exe'
</pre>
Then it will automatically download the executable and store it in a %USER_HOME%/gradlefx/flash/ directory, which will be used by GradleFx.
<br /><br />
I hope this update gave you a clear view of what is coming up. There are of course a lot of other features on my list, but I first wanted to polish the existing features before implementing new ones (although some of these could be seen as new ones...)Yennick Trevelshttp://www.blogger.com/profile/13084772261005156419noreply@blogger.com0tag:blogger.com,1999:blog-6142686052821595387.post-3028732162138762962011-11-05T14:40:00.004+01:002021-05-20T10:34:06.768+02:00Automated Gradle project deployment to Sonatype OSS RepositoryThis post will walk you through the steps to deploy your gradle project to the Sonatype OSS staging repository.
<br />
<br />
<h2>
Prerequisites</h2>
<ul>
<li>Minimum Gradle 1.0 milestone 5</li>
<li>Gpg4zin, you can find the installer on this website: <a href="http://www.gpg4win.org/">http://www.gpg4win.org/</a></li>
</ul>
<h2>
<br /></h2>
<h2>
Configuring your build.gradle file</h2>
First you'll need to configure your build script (build.gradle file). A full working build script of my GradleFx project can be found here:<br />
<a href="https://github.com/GradleFx/GradleFx/blob/develop/build.gradle">https://github.com/GradleFx/GradleFx/blob/develop/build.gradle</a><br />
<br />
These are the steps:<br />
<br />
Apply the maven and signing plugins. The signing plugin will sign your jar and pom files, which is required for deployment to the Sonatype OSS repository. <br />
<pre class="brush:groovy">apply plugin: 'maven'
apply plugin: 'signing'
</pre>
Specify the group and version of your project: <br />
<pre class="brush:groovy">group = 'org.gradlefx'
version = '0.3.1'
</pre>
Define tasks for source and javadoc jar generation. These jars are also required for Sonatype:<br />
<br />
<pre class="brush:groovy">task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from 'build/docs/javadoc'
}
task sourcesJar(type: Jar) {
from sourceSets.main.allSource
classifier = 'sources'
}
</pre>
<br />
Specify your artifacts: <br />
<pre class="brush:groovy">artifacts {
archives jar</pre>
<pre class="brush:groovy"> archives javadocJar
archives sourcesJar
}
</pre>
Configure the signing task by specifying which artifacts to sign, in this case all the artifacts in the archives configuration. This will not yet include the pom file, which will be signed later. <br />
<pre class="brush:groovy">signing {
sign configurations.archives
}
</pre>
Then we need to configure the generated pom file, sign the pom file and configure the Sonatype OSS staging repository.<br />
The <b>'beforeDeployment'</b> line will sign the pom file right before the artifacts are deployed to the Sonatype OSS repository.<br />
The <b>'repository'</b> part configures the Sonatype OSS staging repository. Notice the sonatypeUsername and sonatypePassword variables, these are property variables to which I'll come back to later in this post.<br />
The <b>'pom.project'</b> section configures the generated pom files, you need to specify all this information because it's required for the Sonatype repository (and Maven Central).<br />
<br />
<pre class="brush:groovy">uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
pom.project {
name 'GradleFx'
packaging 'jar'
description 'GradleFx is a Gradle plugin for building Flex and Actionscript applications'
url 'http://gradlefx.github.com/'
scm {
url 'scm:git@github.com:GradleFx/GradleFx.git'
connection 'scm:git@github.com:GradleFx/GradleFx.git'
developerConnection 'scm:git@github.com:GradleFx/GradleFx.git'
}
licenses {
license {
name 'The Apache Software License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution 'repo'
}
}
developers {
developer {
id 'yennicktrevels'
name 'Yennick Trevels'
}
developer {
id 'stevendick'
name 'Steven Dick'
}
}
}
}
}
}
</pre>
That's it for the configuration of your build script. <br />
<h2>
Initial setup</h2>
There are a couple of thing you need to do before you can run the build automatically, like: <br />
<ul>
<li>Register your project at Sonatype</li>
<li>Create a public key pair to sign your jar/pom files</li>
<li>Create a gradle properties file</li>
</ul>
<h5>
Register your project at Sonatype</h5>
First you'll need to register your project at sonatype. Follow the "2. Sign Up" and "3. Create a JIRA ticket" sections on this page: <a href="https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide">https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide</a> <br />
<h5>
Create a public key pair</h5>
A public key pair is needed to sign your jar/pom files. To generate this we need to dive into command line. Follow the "Generate a key pair" and "Distributing your public key" sections on this page: <a href="https://docs.sonatype.org/display/Repository/How+To+Generate+PGP+Signatures+With+Maven">https://docs.sonatype.org/display/Repository/How+To+Generate+PGP+Signatures+With+Maven</a><br />
This will generate a key that will be stored on your computer and on sks-keyservers.net. Remember the password because there is no way to reset or restore it when you forget it. <br />
<h5>
Create a gradle properties file</h5>
Now we'll have to create a gradle.properties file which will contain the public key and sonatype login information. Because this is sensitive information it's best to store this file in your ".gradle" directory (e.g. D:\Users\MyUsername\.gradle) and not under your project. This properties file is used by your gradle build script. The signing.* properties are used and defined by the signing task, the sonatypeUsername and sonatypePassword properties are the variables we defined earlier in our build script. So first create the "gradle.properties" file under D:\Users\MyUsername\.gradle Then add the following properties to the file and change their values: <br />
<pre class="brush: text">signing.keyId=A5DOA652
signing.password=YourPublicKeyPassword
signing.secretKeyRingFile=D:/Users/MyUsername/AppData/Roaming/gnupg/secring.gpg
sonatypeUsername=YourSonatypeJiraUsername
sonatypePassword=YourSonatypeJiraPassword
</pre>
the signing.keyId property is the public key id, you can list your keys with the "gpg --list-keys" command. With this command you'll get an output like this: <br />
<pre class="brush: text">pub 2048R/A5DOA652 2011-10-16
uid MyUid
sub 2048R/F66623G0 2011-10-16
</pre>
<br />
That's it for the initial setup.
<br />
<br />
<h2>
Deployment to the Sonatype OSS Repository</h2>
Once you've done all the previous steps in this post you can deploy your project with just one single command: "gradle uploadArchives"Yennick Trevelshttp://www.blogger.com/profile/13084772261005156419noreply@blogger.com19tag:blogger.com,1999:blog-6142686052821595387.post-7868323748528641052011-05-06T22:27:00.008+02:002013-10-22T11:56:02.721+02:00Building a swc with GradleAfter a search for a better build tool, having used Ant & Maven for a couple of years, I stumbled upon Gradle. A build tool that provides the benefits of Ant & Maven combined into one:<br />
<br />
<ul><li>Dependency Management</li>
<li>Better multi-project support</li>
<li>Flexibility</li>
</ul>Gradle build script are written in Groovy, which allows you to define every step of the build process.<br />
Now, as a Flex developer the first thing I wanted to try out was to build a swc file. I tried to incorporate some multi-project structure into it.<br />
My project structure looks like this:<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbo7ogu2LKT7YZSvTkDFQWG71164VBlij0F9bIV0mu0eBotachyZSSrvpDcm3EVHLLIoeCrWPfSm3sbWfbIgzSrEaqZCoJUX7Ve93uQX_zw0unOVs-OZdMXDkyjnluM9UsE6bxtJNck-OL/s1600/gradlestructure+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbo7ogu2LKT7YZSvTkDFQWG71164VBlij0F9bIV0mu0eBotachyZSSrvpDcm3EVHLLIoeCrWPfSm3sbWfbIgzSrEaqZCoJUX7Ve93uQX_zw0unOVs-OZdMXDkyjnluM9UsE6bxtJNck-OL/s320/gradlestructure+%25282%2529.png" width="320" /></a></div><br />
The settings.gradle file declares which the subprojects are of the mainproject:<br />
<br />
<pre class="brush:groovy">include 'subproject'
</pre><br />
The build script of the main project contains the configuration needed by every subproject. Gradle provides a "subprojects { ... }" structure for this in which you can place all this code. I'm using maven repositories from which my dependencies will be retrieved:<br />
<br />
<pre class="brush:groovy">subprojects {
//retrieve the FLEX_HOME environment variable
FLEX_SDK_HOME = System.getenv()['FLEX_HOME']
configurations {
compile
test
}
repositories {
mavenCentral()
mavenRepo name: 'yoolab-releases',
urls: "http://projects.yoolab.org/maven/content/repositories/releases"
mavenRepo name: 'yoolab-snapshots',
urls: "http://projects.yoolab.org/maven/content/repositories/snapshots"
}
//dependency versions
def spring_actionscript_core_version = '1.2-SNAPSHOT'
def as3commons_collections_version = '1.1'
def as3commons_eventbus_version = '1.1'
def as3commons_lang_version = '0.3.2'
def as3commons_logging_version = '2.0'
def as3commons_reflect_version = '1.3.4'
def flexunit_version = '0.90'
dependencies {
compile group: 'org.springextensions.actionscript',
name: 'spring-actionscript-core',
version: spring_actionscript_core_version,
ext: 'swc'
compile group: 'org.as3commons',
name: 'as3commons-collections',
version: as3commons_collections_version,
ext: 'swc'
compile group: 'org.as3commons',
name: 'as3commons-eventbus',
version: as3commons_eventbus_version,
ext: 'swc'
compile group: 'org.as3commons',
name: 'as3commons-lang',
version: as3commons_lang_version, ext: 'swc'
compile group: 'org.as3commons',
name: 'as3commons-logging',
version: as3commons_logging_version,
ext: 'swc'
compile group: 'org.as3commons',
name: 'as3commons-reflect',
version: as3commons_reflect_version,
ext: 'swc'
test group: 'com.adobe.flexunit',
name: 'flexunit',
version: flexunit_version,
ext: 'swc'
}
}
</pre><br />
The build.gradle file of the subproject contains a compile task (don't mistake this with the 'compile' configuration which I declared in the mainproject's build file). This task can be executed by calling the "gradle compile" command from a command line and it will build the swc file.<br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"></div><pre class="brush: groovy">
task compile << {
println '[compile] Compiling release SWC'
println '[compile] Using Flex SDK at: ' + FLEX_SDK_HOME
def projectName = 'subproject'
def projectVersion = '1.0-SNAPSHOT'
//initialize compc parameters
def compiledSwcFileLocation = buildDir.getAbsolutePath() + '/' + projectName + '-' + projectVersion + '.swc'
def mainSourceLocation = projectDir.getAbsolutePath() + '/src/main/actionscript/'
ant.java(jar: FLEX_SDK_HOME + '/lib/compc.jar',
dir: FLEX_SDK_HOME + '/frameworks',
fork: true,
resultproperty: 'swcBuildResult',
errorProperty: 'errorString') {
arg(value: "-output=" + compiledSwcFileLocation)
arg(value: "-include-sources=" + mainSourceLocation)
//add every dependency path
configurations.compile.files.each{
dep -> arg(value: "-external-library-path+=" + dep.path)
}
}
//handle failed compile
if(ant.properties.swcBuildResult == '1') {
throw new Exception("compc task failed: \n" + ant.properties.errorString);
}
}
</pre><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Gradle has some awesome support for Ant tasks (maybe even better then using them in Ant itself). As you can see I'm using the java Ant task to execute the compc compiler, and I'm providing it some ant property names which I can use after the ant task has been finished.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Gradle takes some getting used to (certainly if you've never used Groovy before), but it's totally worth the effort. I'm going to investigate further into this and see how it scales to bigger projects.</div>Yennick Trevelshttp://www.blogger.com/profile/13084772261005156419noreply@blogger.com2