I am trying to have a auto refresh feature for the grid which basically, updates the grid with latest data from the server every 'n' seconds.
I was able to implement the PollListner whenever the user enables Auto-Refresh.
UI ui= TestUI.getCurrent();
Boolean value = isRefreshChkBox.getValue();
PollListener listener = e -> {
explorer.reloadUI();
};
if (value) {
String refreshRateValue = refreshRateTxtField.getValue();
int refreshRate = Integer.valueOf(refreshRateValue);
int millis = (int) TimeUnit.SECONDS.toMillis(refreshRate);
absUI.setPollInterval(millis);
absUI.addPollListener(listener);
} else {
absUI.setPollInterval(-1);
absUI.removePollListener(listener);
}
With the above code, I add PollListener everytime autorefresh is enabled and I remove it on disable.
I found similar question here VAADIN 7: What is the simplest way to refresh a Vaadin View in 5 minute intervals?
But what I want to understand, is there a better approach to achieve a simple usecase AutoRefresh UI?? where should PollListener be implemented?? I thought of creating PollListener once for the view and just update the PollInterval everytime user changes the refresh rate.
Any pointers on which approach is better or is there completely new concept in Vaadin to achieve this?
TIA
See the correct Answer by Leif Åstrand. I will add a bit of discussion, and a complete example app using both Polling and Push.
Vaadin 8 has two ways to automatically update the display of information without the user making a gesture: Polling & Push.
Polling
In Vaadin 8’s Polling feature, you set a polling interval of milliseconds on your UI subclass. The default value of -1 disables Polling.
myUI.setPollInterval( ( int ) TimeUnit.MINUTES.toMillis( 1 ) ); // Specify milliseconds for polling interval.
When enabled, the Vaadin JavaScript library installed in the user’s web browser checks in with the Vaadin server. Being a PollNotifier, the UI checking-in causes an event to be fired on the server-side.
If you define a class that implements the PollListener interface, your instance will have its poll method invoked.
Upon registering your PollListener. get back a Registration object. That object provides a remove method to unregister your listener, if need be.
You have your choice of defining your PollListener using lambda syntax, an anonymous inner class, or a separately-defined class.
Registration registration = this.addPollListener( new UIEvents.PollListener() {
#Override
public void poll ( UIEvents.PollEvent pollEvent ) {
System.out.println( "TRACE - PollListener::poll running. " + Instant.now() );
…
}
} );
Or, lambda syntax:
Registration registration = this.addPollListener( ( UIEvents.PollListener ) pollEvent -> {
System.out.println( "TRACE - PollListener::poll running. " + Instant.now() );
…
} );
During this invocation, your code can register a Runnable to be invoked at a convenient time with your UI subclass.
That Runnable does the work of updating widgets contained in your UI subclass. Remember to never access or modify widgets from a background thread. You may get away with it, or you may cause terrible things to happen. Be safe: Always call UI::access to pass a Runnable that accesses the widgets. That Runnable will be run on the main user-interface thread of your web app, the thread in charge of your UI subclass instance.
getUI().access( new Runnable() {
#Override
public void run ( ) {
subscriber.refresh( new ArrayList <>( statusList ) ); // Copy the list in case the `Grid` modifies it, such as sorting.
}
} );
Pros
The upside of using the Polling feature is that the programming you must do is simpler than with Push (discussed below). Polling is likely a better route to take when learning about automated non-user-generated updates.
One simple aspect is that each instance of your UI subclass is in charge of its own polling, choosing if and when to do polling and controlling how often to poll. Each UI subclass instance calls its own setPollInterval method. More polling may be nice for the user, but the chattiness increases network traffic, thereby making your network admin cranky. So you can tune the frequency by UI subclass instance. Remember that not only does each user have their own UI subclass instance, but also, Vaadin 8 is capable of multi-window/tab apps. One web app in each web browser can have multiple windows/tabs open, each running their own instance of the same or different UI subclasses.
Cons
One downside aesthetically is that polling breaks the request-response elegance of the HTTP design. While this is a pet-peeve of mine, that ship has sailed long ago, so I'll not waste bytes here ranting about using a document-delivery system as an interactive client-server app architecture.
A more practical downside is unnecessary traffic on the network. If you are able to use Push via WebSocket or Webpush, then an open connection is maintained between client and server with very little traffic all the while until the server generates an event to be communicated to the client. But be aware that WebSocket is easily defeated by firewalls & proxies, and Webpush may not be implemented/supported, in which case the Push implementation in Vaadin (the Atmosphere Framework library by async-io.org) may fall back to polling techniques.
Another downside is inefficiency of each client doing its own repeated polling and each triggering a separate execution on the server-side such as the search for fresh data in the database. If you have many clients all consuming the same set of immutable objects, then Push can be more efficient doing a single search for fresh data and delivering the same bunch of data objects to all the clients.
Push
The combination of Vaadin with Atmosphere (linked above) vastly simplifies using Push technology in your web app. Nevertheless, it is a bit more complicated with more moving parts than seen with the Polling feature.
Firstly, enable Push with the #Push annotation on your UI subclass.
Then schedule the firing of an event every minute using a ScheduledExecutorService. Set up that executor with a ServletContextListener. See example code below for all this.
Pros
Push can be quite efficient in terms of network traffic able to use WebSocket technology or Webpush, as mentioned above.
Cons
Unfortunately WebSocket can be defeated by firewalls & proxies. And Webpush is new and may not be widely supported. In this case, Vaadin/Atmosphere may fall-back to using a polling approach.
Another downside is that the coding is a bit more complex. A programmer new to this work may take a while to grasp the various moving pieces.
You need a background thread on the server-side to track the time, in our case firing every minute. The modern approach to that is using a ScheduledExecutorService to handle the threading and firing schedule.
To setup that executor service, you will need to implement a ServletContextListener as discussed below.
Be aware that some of the push approaches, especially WebSocket, involve maintaining an open network connection. So this consumes resources such as port numbers on your server machine.
Example app
I built a complete working example app using Vaadin 8.6beta1. This app supports both Polling and Push. Not sure if you would ever mix both in a real web app, but perhaps.
Access the main files on my Google Drive. Add to a project created via the Maven archetype vaadin-archetype-application provided by Vaadin Ltd.
Caveat: This example was cobbled together part-time over days. So it may or may not be production-ready code, and may or may not show proper technique. But hopefully it will help to guide a newbie.
Caveat: I am not an expert in this arena. So take all my discussion above and my example code here with a grain-of-salt. Do your own research and study.
This app allows you to enable and disable each approach via radio buttons. You can also force an immediate refresh by clicking the Refresh manually now button.
The green-shading indicates changed values since the last refresh.
You can run multiple windows. Watch them update together or separately or not all, depending on your radio button settings.
Database
The main idea of this example app is to simulate a database maintaining a current status of some ten pieces of equipment/processes/people/whatever. Each status in identified by a number 1-10. Each has a status with a domain of ten values, 1-9. And each status records the moment it was last updated.
These ten status records are displayed as rows in a Vaadin Grid widget.
All this data is recorded in a relational database, the H2 Database Engine. As a demo, we’ve no need for persistence, so the database is in-memory. A background thread randomly updates the status rows in the database.
MyDbService.java
This database-service code establishes our in-memory H2 database, defining the table for our Status, and populating ten rows. This class also can randomly update the value of some of the rows. And you can ask to retrieve a List of Status objects representing the currently stored values.
Status.java
Each status record is represented in Java by the Status class, a simple POJO.
Lifecycle
Vaadin is based on Java Servlet technology. Your Vaadin app is one big Servlet implementation. As a servlet, it responds to incoming requests by the users’ web browsers.
Before that first incoming request, we need to do some set-up work. For one thing, we need to establish and populate that database with our ten status records.
The Servlet specification requires all web containers to support the ServletContextListener interface. If you write a class implementing that interface, and declare it to the web container, then it will be invoked before the first request and after the last request.
In our example, we use that hook to establish the database. We also set up a background thread that randomly changes our stored status records to simulate either users’ updates or fresh data from a feed.
Context listener
Here is our example ServletContextListener.
The easiest way to declare its presence to our web container is by the #WebListener annotation but you can choose other routes as needed in your deployment scenario.
#WebListener
public class MyServletContextListener implements ServletContextListener {
…
MyUI.java
The entry point into this Vaadin web app is our subclass of UI, MyUI.java. It has two jobs: (a) Get our user-interface content on-screen, and (b) Register itself as a PollListener to react to polling updates.
DataDisplayLayout.java
Here is our user-interface content. This is the centerpiece of this example app. It displays the Vaadin Grid whose display is to be updated with fresh data.
DataDisplayLayoutRefreshManager.java
This manager oversees the pub-sub (Publish-Subscribe) model of signing up instances of our DataDisplayLayout that want to be updated via Push.
A collection of weak references are used here to track the subscribers. So the subscribing DataDisplayLayout instance can gracefully notify of their desire to no longer be updated, or the instance can simply go out-of-scope to eventually be dropped as a subscriber.
The Polling approach does not need this manager, as each instance of our UI subclass (MyUI) is individually polling the server.
mytheme.scss
The green coloring of the cell in the Vaadin Grid denoting a fresh value is set via CSS. In Vaadin 8, we do this by editing the mytheme.scss file found buried in your project’s webapp folder.
Here we define the style name fresh_row.
#import "../valo/valo.scss";
#mixin mytheme {
#include valo;
// Insert your own theme rules here
.v-grid-row.fresh_row > td:nth-child(2) {
background-color: honeydew;
}
}
We must assign that style name to our Vaadin Grid rows by implementing a style generator.
this.grid.setStyleGenerator( ( StyleGenerator ) o -> {
Status s = ( Status ) o;
if ( s.getUpdated().isAfter( this.whenRowLastUpdated ) ) {
return "fresh_row";
} else {
return null;
}
} );
There are basically two ways of updating a Vaadin UI from background activity: poll and push. Each has their own pros and cons.
Polling is the technically more simple approach. It's based on a timer in the browser that triggers a request at a regular interval. Any pending changes will be delivered to the client in the response to that request. In addition, you can add a listener that gets run for every such request so that you can manually check for changes and if needed, update the UI.
Push is based on keeping a persistent connection open between the client and the server, so that the server can send changes to the client immediately instead of having to wait until the client opens a connection and asks for changes. The benefit here is that changes can be sent to the client immediately when they happen, instead of only at regular intervals.
Which to use depends on your requirements. Polling may use slightly less resources because there's no need to keep a connection open all the time. Polling may also be beneficial if there is no server-side trigger when the data changes, but instead, the server-side logic would still have to periodically explicitly check whether anything has changed. The main benefit of push is that changes can be sent immediately when something happens.
Related
I am trying to make a demo Android project using Redux architecture but I am having trouble to wrap my head around showing flash messages for example as a reaction to successful/failed async action.
If it was a long-lived view, that informs user about the result I would just dispatch another action which alters state with particular flag and display the view. However if I want to use Toast or SnackBar for it, I don't have means to cancel the flag and it would just show the message again after another state change.
I am new to Redux, but I read that reducers must be pure functions and if I understand the pure function concept correctly, showing a flash message is a side-effect which is not allowed. So I can't dispatch an action that would be reduced to only invoke without altering the state.
So the only option I can see is that I handle all async operations outside the Redux flow, dispatch actions in reaction to those events and show flash messages in event handlers as well. But to my mind, every UI change is also a change in state, and not reflecting it in Store is a problem. So by doing this I feel like violating Redux pattern and taking a lot from the architecture itself as it will reduce its testing capabilities.
Is there a way out?
Redux describe a component such Middleware.
http://redux.js.org/docs/advanced/Middleware.html
Quote from article:
'It provides a third-party extension point between dispatching an action, and the moment it reaches the reducer.'
You can create middleware for this side effect. In your system you have actions such as SetSuccessLoadingAction and SetFailedLoadingAction. In your middleware you can determine these actions and do what you need.
For example you can see how middleware works for another side affect - logging every incomming action.
https://github.com/zyvpeople/Redux
I'm currently on a study project involving Domain-driven design (DDD) and integration scenarios of multiple domains.
I have a use case in one of my bounded context where I need to contact another BC to validate an aggregate. In fact, there could be several BC to ask for validation data in the future (but no for now).
Right now, I'm suffering from DDD obsessive compulsive disorder nervous breakdown where I cannot found a way to apply patterns correctly (lol). I would really appreciate some feedback from people about it.
About the 2 bounded contexts.
- The first one (BC_A) where the use case is taking place would contain a list of elements that are related to the user.
- The external one (BC_B) has some knowledge about those elements
* So, a validation request from BC_A to BC_B would ask a review of all elements of the aggregate from BC_A, and would return a report containing some specifications about what to do with those elements (if we should keep it or not, and why).
*The state of the aggregate would pass through (let say) "draft" then "validating" after a request, and then depending on the report sent back, it would be "valid" or "has_error" in case there is one. If the user later choose to not follow the spec, it could pass the state of the aggregate to "controlled" meaning there is some error but we do not taking care of it.
The command is ValidateMyAggregateCommand
The use case is:
get the target aggregate by id
change its state to "validating"
persist the aggregate
make validation call (to another BC)
persist the validation report
acknowledge the validation report with the target aggregate (which will change its state again depending on the result, should be "OK" or "HAS_ERROR")
persist the aggregate again
generate a domain event depending on the validation result
it contains 8 steps, possibly from 1 to 3 transactions or more.
I need to persist the validation report localy (to access it in the UI) and I think I could do it:
after the validation call independently (the report being its own aggregate)
when I persist the target aggregate (it would be inside it)
I prefer the first option (step 5) because it is more decoupled - even if we could argue that there is an invariant here (???) - and so there is a consistency delay between the persistance of the report and the acknownledgement by the aggregate.
I'm actually struggling with the call itself (step 4).
I think I could do it in several ways:
A. synchronous RPC call with REST implementation
B. call without a response (void) (fire and forget) letting several implementations options on the table (sync/async)
C. domain event translated into technical event to reach other BC
A. Synchronous RPC call
// code_fragment_a
// = ValidateMyAggregateCommandHandler
// ---
myAggregate = myAggregateRepository.find(command.myAggregateId()); // #1
myAggregate.changeStateTo(VALIDATING); // #2
myAggregateRepository.save(myAggregate); // #3
ValidationReport report = validationService.validate(myAggregate); // #4
validationReportRepository.save(report); // #5
myAggregate.acknowledge(report); // #6
myAggregateRepository.save(myAggregate); // #7
// ---
The validationService is a domain service implemented in the infrastructure layer with a REST service bean (could be local validation as well but not in my scenario).
The call needs a response immediately and the caller (the command handler) is blocked until the response is returned. So it introduces a high temporal coupling.
In case the validation call fails because of technical reasons, we take an exception and we have to rollback everything. The command would have to be replayed later.
B. Call without response (sync or async)
In this version, the command handler would persist the "validating" state of the aggregate, and would fire (and forget) the validation request.
// code_fragment_b0
// = ValidateMyAggregateCommandHandler
// ---
myAggregate = myAggregateRepository.find(command.myAggregateId()); // #1
myAggregate.changeStateTo(VALIDATING); // #2
myAggregateRepository.save(myAggregate); // #3
validationRequestService.requestValidation(myAggregate); // #4
// ---
Here, the acknowledgement of the report could happen in a sync or async manner, inside or outside the initial transaction.
Having this code above in a dedicated transaction allows failures in validation call to be harmless (if we have a retry mechanism in the impl).
This solution would allow to start with a sync communication quickly and easily, and switch to an async one later. So it is flexible.
B.1. Synchronous impl
In this case, the implementation of the validationRequestService (in the infrastructure layer) does a direct request/response.
// code_fragment_b1_a
// = SynchronousValidationRequestService
// ---
private ValidationCaller validationCaller;
public void requestValidation(MyAggregate myAggregate) {
ValidationReport report = validationCaller.validate(myAggregate);
validationReportRepository.save(report);
DomainEventPublisher.publish(new ValidationReportReceived(report))
}
// ---
The report is persisted in a dedicated transaction, and the publishing of an event activate a third code fragment (in the application layer) that do the actual acknowledgment work on the aggregate.
// code_fragment_b1_b
// = ValidationReportReceivedEventHandler
// ---
public void when(ValidationReportReceived event) {
MyAggregate myAggregate = myAggregateRepository.find(event.targetAggregateId());
ValidationReport report = ValidationReportRepository.find(event.reportId());
myAggregate.acknowledge(report);
myAggregateRepository.save(myAggregate);
}
// ---
So here, we have an event from infra layer to the app layer.
B.2. Asynchronous
The asynchronous version would change the previous solution in the ValidationRequestService impl (code_fragment_b1_a). The use of a JMS/AMQP bean would allow to send a message in a first time, and receive the response later independently.
I guess the messaging listener would fire the same ValidationReportReceived event, and the rest of the code would be the same for code_fragment_b1_b.
As I write this post, I realize this solution (B2) present a nicer symetry in the exchange and better technical points because it is more decoupled and reliable regarding the network communications. At this point it is not introducing so much complexity.
C. Domain events and bus between BCs
Last implementation, instead of using a domain service to request a validation from other BC, I would raise a domain event like MyAggregateValidationRequested. I realize it is a "forced" domain event, ok the user requested it but it never really emerge in conversation but still it is a domain event.
The thing is, I don't know yet how and where to put the event handlers. Should the infrastructure handlers take it directly ?
Should I translate the domain event into a technical event before sending it to its destination ???
technical event like some kind of DTO if it was a data structure
I guess all the code related to messaging belong to the infrastructure layer (port/adapter slot) because they are used to communicate between systems only.
And the technical events that are transfered inside those pipes with their raising/handling code should belong to the application layer because like commands, they end up on a mutation of the system state. They coordinates the domain, and are fired by the infra (like controllers firing application service).
I read some solutions about translating events in commands but I think it makes the system more complex for no benefits.
So my application facade would expose 3 types of interacion:
- commands
- queries
- events
With this separation, I think we can isolate commands from UI and events from other BCs more clearly.
Ok, I realize that post is pretty long and maybe a little bit messy, but this is where I'm stuck, so I thank you in advance if you can say something that could help me.
So my problem is that I'm struggling with the integration of the 2 BC.
Different solutions: - The service RPC (#A) is simple but limit the scale, - the service with messaging (#B) seems right but I still need feedback, - and the domain events (#C) I don't know really how to cross boudaries with that.
Thank you again!
I have a use case in one of my bounded context where I need to contact another BC to validate an aggregate.
That's a really weird problem to have. Typically, aggregates are valid, or not valid, entirely dependent on their own internal state -- that would be why they are aggregates, and not merely entities in some larger web.
In other words, you may be having trouble applying the DDD patterns because your understanding of the real problem you are trying to solve is incomplete.
As an aside: when asking for help in ddd, you should adhere as closely as you can to your actual problem, rather than trying to make it abstract.
That said, there are some patterns that can help you out. Udi Dahan walks through them in detail in his talk on reliable messaging, but I'll cover the high points here.
When you run a command against an aggregate, there are two different aspects to be considered
Persisting the change of state
Scheduling side effects
"Side effects" can include commands to be run against other aggregates.
In your example, we would see three distinct transactions in the happy path.
The first transaction would update the state of your aggregate to Validating, and schedule the task to fetch the validation report.
That task runs asynchronously, querying the remote domain context, then starts transaction #2 in this BC, which persists the validation report and schedules a second task.
The second task - built from the data copied into the validation report - starts transaction #3, running a command against your aggregate to update its state. When this command is finished, there are no more commands to schedule, and everything gets quiet.
This works, but it couples your aggregates perhaps too tightly to your process. Furthermore, your process is disjoint - scattered about in your aggregate code, not really recognized as being a first class citizen.
So you are more likely to see this implemented with two additional ideas. First, the introduction of a domain event. Domain events are descriptions changes of state that are of special significance. So the aggregate describes the change (ValidationExpired?) along with the local state needed to make sense of it, publishing the event asynchronously. (In other words, instead of asynchronously running an arbitrary task, we run asynchronously schedule a PublishEvent Task, with an arbitrary domain event as the payload).
Second, the introduction of a "process manager". The process manager subscribes to the events, updates its internal state machine, and schedules (asynchronous) tasks to run. (These tasks are the same tasks that the aggregate was scheduling before). Note that the process manager doesn't have any business rules; those belong in the aggregates. But they know how to match commands with the domain events they generate (see the messaging chapter in Enterprise Integration Patterns, by Gregor Hohpe), to schedule timeout tasks that help detect which scheduled tasks haven't completed within their SLA and so on.
Fundamentally, process managers are analogous to aggregates; they themselves are part of the domain model, but access to them is provided to them by the application component. With aggregates, the command handler is part of the application; when the command has been processed by the aggregate, it's the application that schedules the asynchronous tasks. The domain events are published to the event bus (infrastructure), and the application's event handlers subscribe to that bus, loading the process managers via persistence, passing the domain event to be processed, using the persistence component again to save the updated process manager, and then the application schedules the pending tasks.
I realize it is a "forced" domain event, ok the user requested it but it never really emerge in conversation but still it is a domain event.
I wouldn't describe it as forced; if the requirement for this validation process really comes from the business, then the domain event is a thing that belong in the ubiquitous language.
Should I translate the domain event into a technical event before sending it to its destination
I have no idea what you think that means. Event is a message describing something that happened. "Domain event" means that the something happened within the domain. It's still a message to be published.
I have the following situation:
I have a Service that checks periodically for new data over the internet,
when new data are available they are downloaded and saved on sqlite.
when the save to db is complete the service broadcasts an intent so that the activity knows to pull the new data from the db.
The user might want to request an immediate update...
...in that case I use a Messenger to request the Service to look for new data
Here is the problem:
the user is notified that a request is ongoing, but it might take a while, can be unsuccessful, could never return...
currently I get a message (using a Messenger) back from the Service to the Activity informing of the result of the request, or, if I get no message, in x seconds I inform the user that the request was unsuccessful.
Please can you suggest a different approach?
I don't like to wait
for a message and if after x seconds none is received inform the
user, is there a better way?
You've got the basics, so not much else to recommend. I'll just show you a few alternatives:
You can use ContentObserver and update the UI once there is new data in the database (no need to wait for a message from the service).
If you've got a lot of communication between Service <-> UI components, it might be easier if you take a look at Otto, EventBus or just restructure your code around Observables / RxJava.
You can move the Timeout logic to the service (it will be easier this way since all the error handling will be in a single place) and just return the error message to the UI. Most network frameworks allow you to set a Connection Timeout parameter and will fail the request after this time is reached. If you haven't looked at network frameworks yet - Retrofit + OkHttp is a great starting point.
You might consider optimistic rendering/optimistic updates- A pattern in which you update the UI on client as if it has being successful on the server.
Once you get response from the server you update the UI accordingly.You can refer apps with new designs like google hangouts.
For more info refer this discussions:
what is `optimistic updates` in front-end development
https://ux.stackexchange.com/questions/17514/should-we-be-optimistic-or-pessimistic-with-ui-updates-on-ajax-requests
I guess using this approach will give better usability to your app.
The current implementation looks ok. However you can improve it by following this talk-https://www.youtube.com/watch?v=BlkJzgjzL0c
If you think about this as a Model View Controller problem, the issue here is the lack of a model to represent the state of the Service. When the Service is performing the refresh, this "state" needs to reflected in your UI. Thus the Service needs to record this somewhere that the UI can access.
One option is simply a piece of shared memory, such as a Singleton object or even a static member variable (not recommended). Another option is to keep that state in your database.
Another issue is notifying the UI when this state changes. As mentioned by other posts there are multiple ways of doing this such as a LocalBroadcast, message bus like Otto, ContentObservers, etc.
We are currently porting our app to vaadin 7 and I want to track wether a user has been active during the last 30s or so.
We used to track user activity in a custom CommunicationManager, but since this class is deprecated, I figured we might have to try differently.
I created an extension that I extend the UI with.
For simplicity's sake let's say, we count clicking and keyboard usage as user activity:
// this is the extend method in the extension connector
#Override
protected void extend (ServerConnector target) {
UIConnector uiConnector = (UIConnector) target;
VUI uiWidget = uiConnector.getWidget();
uiWidget.addDomHandler(this.keyPressed(), KeyPressEvent.getType());
uiWidget.addDomHandler(this.mouseClicked(), ClickEvent.getType());
}
The extension will then schedule a timer that will call the server via RPC every 30s, but only if the user has been active.
This Timer works. What does not work is the DOM Events, they never seem to reach the Event Listeners I added.
What am I doing wrong?
Based on your implementation, I would suggest you give Refresher add-on a try. It works in similar manner but gives you more control regarding polling interval, server-side listener. Plus, you don't have to maintain it.
The other alternative would be taking advantage of Vaadin polling support (see https://vaadin.com/wiki/-/wiki/Main/Using%20polling).
I'm currently working on a (rather large) pet project of mine , a Swing application that by it's very nature needs to be multi-threaded. Almost all user interactions might fetch data from some remote servers over the internet , since I neither control these servers nor the internet itself, long response times are thus inevitable. A Swing UI obviously cannot repaint itself while the EDT is busy so all remote server calls need to be executed by background thread(s).
My problem:
Data fetched by the background threads gets 'enriched' with data from a local (in-memory) database (remote server returns IDs/references to data in the local database). This data later eventually gets passed to the EDT where it becomes part of the view model. Some entities are not completely initialized at this point (lazy-fetching enabled) so the user might trigger lazy-fetching by e.g. scrolling in a JTable. Since the hibernate session is already closed this will trigger a LazyInitializationException. I can't know when lazy-fetching might be triggered by the user so creating a session on demand/attaching the detached object will not work here.
I 'solved' this problem by:
using a single (synchronized , since Session instances are not thread-safe) Session for the whole application
disabling lazy-fetching completely
While this works, the application's performance has suffered greatly (sometimes being close to unusable). The slowdown is mainly caused by the large number of objects that are now fetched by each query.
I'm currently thinking about changing the application's design to 'Session-per-thread' and migrating all entities fetched by non-EDT threads to the EDT thread's Session (similar to this posting on the Hibernate forums).
Side-note: Any problems related to database updates do not apply since all database entities are read-only (reference data).
Any other ideas on how to use Hibernate with lazy-loading in this scenario ?
Don't expose the Session itself in your data API. You can still do it lazily, just make sure that the hydration is being done from the 'data' thread each time. You could use a block (runnable or some kind of command class is probably the best Java can do for you here unfortunately) that's wrapped by code that performs the load async from the 'data' thread. When you're in UI code, (on the UI thread of course) field some kind of a 'data is ready' event that is posted by the data service. You can then get the data from the event use in the UI.
You could look have a look at Ebean ORM. It is session-less and lazy loading just works. This doesn't answer your question but really proposes an alternative.
I know Ebean has built in support for asynchronous query execution which may also be interesting for your scenario.
Maybe worth a look.
Rob.
There are two distinct problems, that should get resolved seperately:
Handling of Hibernate Sessions in Swing Applications. Let me recommend my own article, regarding this problem: http://blog.schauderhaft.de/2008/09/28/hibernate-sessions-in-two-tier-rich-client-applications/
The basic idea is to have a session for every frame, excluding modal frames which use the session of the spawning frame. It is not easy but it works. Meaning, you won't get any LLEs anymore.
How to get your GUI thread separated from the back end.
I recommend to keep the hibernate objects strictly on the back end thread they originate from. Only give wrapper objects to the ETD. If these wrapper objects are asked for a value, they create a request which gets passed to the backend thread, which eventually will return the value.
I'd envision three kinds of wrapper Implementations:
Async: requests the value, and gets notified when the value is available. It would return immediately with some dummy value. On notification it will fire a PropertyChange event i.O. to inform the GUI about the 'changed' value (changed from unknown to a real value).
Sync: requests the value and waits for it to be available.
Timed: a mixture between the two, waiting for a short time (0.01) seconds, before returning. This would avoid plenty change events, compared to the async version.
As a basis for these wrappers a recommend the ValueModel of the JGoodies Binding library: http://www.jgoodies.com/downloads/libraries.html
Obviously You need to take care that any action is only performed on actually loaded values, but since you don't plan on doing updates this shouldn't be to much of an issue.
Let me end with a warning: I have thought about it a lot, but never actually tried it, so move with care.