"core" refers to the initial piece of the application that is loaded.
In order to bind url to places, GWT uses PlaceTokenizer<P extends Place>. When loading the application from the url, it calls the method P getPlace(String token) to retrieve a new instance of the place to call.
due to the asynchronous nature of code splitting, I can't create the place inside a runAsync in this method. So I have to put all the places of my app in the core.
To link places to activity, GWT callsActivity getActivity(Place place) (from com.google.gwt.activity.shared.ActivityMapper) to retrieve a new instance of the activity.
Once again, i have to put all my activities in the core.
Here's what I want to try: Write a custom com.google.gwt.place.shared.Delegate that
bind itself on PlaceChangeRequestEvent. If the AppPiece corresponding to the requestedPlace isn't loaded, it calls event.setWarning(NEED_TO_LOAD_MODULE)
in the confirm(String message) method, always return false when the message equals NEED_TO_LOAD_MODULE (so it doesn't bother the user), and load the module via RunAsync.
Once the module is loaded, call goTo(requestedPlace)
Each AppPiece of my application contains a bunch of activies and the corresponding views. Since the mappers are only called when PlaceChangeEventis fired, i could generate a new instance of my activity via AppPiece.getSomeActivityInstance().
I'm pretty sure this will work, but what bother me is that
Finding wich AppPiece to load depending on the requestedPlace will force me to write code that will be very similar to my mappers
I would like to have my places inside the corresponding AppPiece
Overriding Delegate for this purpose is tricky, and I'm looking for a better solution
You don't have to put all your activities in the core (as you call it): while an Activity instance is retrieved synchronously, it's allowed to start asynchronously. This is where you'd put your GWT.runAsync call.
See http://code.google.com/p/google-web-toolkit/issues/detail?id=5129 and https://groups.google.com/d/topic/google-web-toolkit/8_P_d4aT-0E/discussion
Related
I have splitted my application into two main areas.
Part(A)
PartStashContainer(B)
The content of A should be set based on what user wants.
So basically i can have 1..N classes which could be used in Class URI of Part in application model.
I don't know if i should replace the whole Part(A) with new dynamically created Part(C) which has content i want, or i should somehow to modify the existing Part (call setContributionURI, or setObject methods on Part object?).
It does make more sense to me to modify the existing Part, because it is defined in Application model and therefore already describing the location where the content should be.
Possible solutions:
Modify the Part object so it "reload" its content based on new setup (But how? Can setContributionURI or setObject methods help?)
Remove the old Part and add dynamically on same place in Application model the new Part (using EModelService and EPartService).
other solution??
If you want to reuse the Part then do something like:
MPart part = find or inject your part
MyClass myClass = (MyClass)part.getObject();
... call a method of MyClass to change the contents
MyClass is the class you specify for the object in the application model. You should add a method to that to let you change the contents.
Don't try to call setObject, this is really only for use by Eclipse. I don't think setContributionURI would do anything after the part is created (but I am not sure).
If you want to use different classes for the different data then you really should use different Parts.
Hi I am trying to learn JAVA deeply and so I am digging into the JDK source code in the following lines:
URL url = new URL("http://www.google.com");
URLConnection tmpConn = url.openConnection();
I attached the source code and set the breakpoint at the second line and stepped into the code. I can see the code flow is: URL.openConnection() -> sun.net.www.protocol.http.Handler.openConnection()
I have two questions about this
First In URL.openConnection() the code is:
public URLConnection openConnection() throws java.io.IOException {
return handler.openConnection(this);
}
handler is an object of URLStreamHandler, define as blow
transient URLStreamHandler handler;
But URLStreamHandler is a abstract class and method openConnection() is not implement in it so when handler calls this method, it should go to find a subclass who implement this method, right? But there are a lot classes who implement this methods in sun.net.www.protocol (like http.Hanlder, ftp.Handler ) How should the code know which "openConnection" method it should call? In this example, this handler.openConnection() will go into http.Handler and it is correct. (if I set the url as ftp://www.google.com, it will go into ftp.Handler) I cannot understand the mechanism.
second. I have attached the source code so I can step into the JDK and see the variables but for many classes like sun.net.www.protocol.http.Handler, there are not source code in src.zip. I googled this class and there is source code online I can get but why they did not put it (and many other classes) in the src.zip? Where can I find a comprehensive version of source code?
Thanks!
First the easy part:
... I googled this class and there is source code online I can get but why they did not put it (and many other classes) in the src.zip?
Two reasons:
In the old days when the Java code base was proprietary, this was treated as secret-ish ... and not included in the src.zip. When they relicensed Java 6 under the GPL, they didn't bother to change this. (Don't know why. Ask Oracle.)
Because any code in the sun.* tree is officially "an implementation detail subject to change without notice". If they provided the code directly, it helps customers to ignore that advice. That could lead to more friction / bad press when customer code breaks as a result on an unannounced change to sun.* code.
Where can I find a comprehensive version of source code?
You can find it in the OpenJDK 6 / 7 / 8 repositories and associated download bundles:
http://hg.openjdk.java.net/jdk6/jdk6 - http://download.java.net/openjdk/jdk6/
http://hg.openjdk.java.net/jdk7/jdk7 - http://download.java.net/openjdk/jdk7/
http://hg.openjdk.java.net/jdk8/jdk8
Now for the part about "learning Java deeply".
First, I think you are probably going about this learning in a "suboptimal" fashion. Rather than reading the Java class library, I think you should be reading books on java and design patterns and writing code for yourself.
To the specifics:
But URLStreamHandler is a abstract class and method openConnection() is not implement in it so when handler calls this method, it should go to find a subclass who implement this method, right?
At the point that the handler calls than method, it is calling it on an instance of the subclass. So finding the right method is handled by the JVM ... just like any other polymorphic dispatch.
The tricky part is how you got the instance of the sun.net.www.protocol.* handler class. And that happens something like this:
When a URL object is created, it calls getURLStreamHandler(protocol) to obtain a handler instance.
The code for this method looks to see if the handler instance for the protocol already exists and returns that if it does.
Otherwise, it sees if a protocol handler factory exists, and if it does it uses that to create the handler instance. (The protocol handler factory object can be set by an application.)
Otherwise, searches a configurable list of Java packages to find a class whose FQN is package + "." + protocol + "." + "Handler", loads it, and uses reflection to create an instance. (Configuration is via a System property.)
The reference to handler is stored in the URL's handler field, and the URL construction continues.
So, later on, when you call openConnection() on the URL object, the method uses the Handler instance that is specific to the protocol of the URL to create the connection object.
The purpose of this complicated process is to support URL connections for an open-ended set of protocols, to allow applications to provide handlers for new protocols, and to substitute their own handlers for existing protocols, both statically and dynamically. (And the code is more complicated than I've described above because it has to cope with multiple threads.)
This is making use of a number of design patterns (Caches, Adapters, Factory Objects, and so on) together with Java specific stuff such as the system properties and reflection. But if you haven't read about and understood those design patterns, etcetera, you are unlikely to recognize them, and as a result you are likely to find the code totally bamboozling. Hence my advice above: learn the basics first!!
Take a look at URL.java. openConnection uses the URLStreamHandler that was previously set in the URL object itself.
The constructor calls getURLStreamHandler, which generates a class name dynamically and loads, and the instantiates, the appropriate class with the class loader.
But URLStreamHandler is a abstract class and method openConnection()
is not implement in it so when handler calls this method, it should go
to find a subclass who implement this method, right?
It has to be declared or abstract or implemented in URLStreamHandler. If you then give an instance of a class that extends URLStreamHandler with type URLStreamHandler and call the openConnection() method, it will call the one you have overriden in the instance of the class that extends URLStreamHandler if any, if none it will try to call the one in URLStreamHandler if implemented and else it will probably throw an exception or something.
What is the best practise to update Activity state on Place change? Imagine you have an activity with view that displays list of categories and list of items in the category. If different category is selected then app goes to new place with category ID. I want then to only refresh items and not to create new activity that also re-reads category list.
My current approach is like this:
public class AppActivityMapper implements ActivityMapper {
private ItemListActivity itemListActivity;
...
public Activity getActivity(final Place place) {
final Activity activity;
if (place instanceof ItemListPlace) {
if (itemListActivity == null) {
itemListActivity = new ItemListActivity((ItemListPlace) place, clientFactory);
} else {
itemListActivity.refresh((ItemListPlace) place);
}
activity = itemListActivity;
} else {
itemListActivity = null;
}
...
return activity;
}
...
Alternatives are:
listen to PlaceChangeEvents from within the activity (you can then use a FilteredActivityMapper and CachingActivityMapper for the caching of the activity in your ActivityMapper, so that it's reduced to only create a new activity when asked). †
have some component listen to PlaceChangeEvents and translate them to business-oriented events, the activity then listens to those events rather than PlaceChangeEvents, otherwise the same as above.
decouple the activity from the "screen", make the "screen" a singleton with a reset() method and call that method from the activity's start (possibly passing the category ID as an argument in this case). The "screen" being a singleton could then make sure to load the categories list only once.
in your case, you could also simply put the categories list in a shared cache, so that you don't have to reuse your activity by can create a new one, the categories list will be retrieved once and put in the cache, subsequent activity instances will just use what's in the cache. This is similar to the above, but simpler, and the cache could be used by other parts of the application.
I'd personally rather go with your approach though (with a small exception, see below), as it's the simplest/easiest. Decoupling the activity from the "screen" is also an option; the GWT Team started exploring this approach in the Expenses sample (decoupling the activity responsibility from the presenter responsibility with using MVP) without ever finishing it unfortunately.
Other than that, I don't think any best practice has really emerged for now.
†. I don't like coupling my activities with the places they're used with (I don't quite like the coupling for the goTo calls either, but haven't yet found a clean and simple alternative), so I'd rather not go with this option; and similarly, I'd not pass the place to the activity constructor and refresh method like you did, but rather extract the information out of the place and pass it to the activity (e.g. in your case, only give the category ID to the activity, not the ItemListPlace instance; I would then simply call setCategory in all cases, and not even pass the category ID to the constructor).
In my opinion,
The role of the ActivityMapper is to give you back an Activity from a Place.
The role of the ActivityManager is to start the Activity given back from the ActivityMapper and to stop the current one if different. In your case you would like to "update/refresh" the current Activity.
So I would modify the ActivityMapper so as it will allways give me back the same instance of Activity for a given type of Place. A good way to do so could be to use GIN and use the singleton scope ...in(Singleton.class) to inject your Activity.
If you do that, when changing the url, if the place stays the same (meaning your url has the same word after # and before :) so that the Type of your place stays the same, the ActivityMapper will give you back the same instance of Activity so the ActivityManager will do nothing on the Activity. Check l.126 of ActivityManager
if (currentActivity.equals(nextActivity)) {
return;
}
For me you have 2 options there. The first one, as Thomas said , is to listen to PlaceChangeEvent in your Activity. The new Place you will receive can have new parameters inside based on the new url given and you can "update/refresh" your Activity.
The second one, that I find more in line with the Activity/Place pattern is to modify the ActivityManager so that it calls an update(Place) method on the Activity when the Activity given back by the ActivityMapper is the same that the current Activity.
I haven't tried any of these solutions yet but I will soon ... I might be able to update that post at that time.
You can find more information in this article I wrote on my blog on that topic
Here is a little schema I made to help me understand the pattern, hope it will help :
I would not do any logic in my ActiviyMapper except returning an activity, by creating a new one or giving a previous one (or null). According to me, the mapper doesn't have to know about refresh() or what activities do.
If that, then the logic of 'refresh()' would be given to the activy through the place which holds a token. That token should be holding the information about either what is the state of the request (a new page, reload, an id, etc).
In the activity, first, it asks for the View, the one related to this activity (tip : a singleton given by a 'ClientFactory' is good practice), then it creates a presenter for that view, and bind them together.
Lastly, the activity will use the token from the place to provide any information about state to the presenter. And then, it adds the view in the page.
It's good to know by default, with places and activies, going to the same place doesn't do anything (no reload). But you can take care of it with token and activity-mapper easily.
Hope you'll find an adapted solution for you case. Goodluck.
Does anyone have or know of an example which demonstrates loading data via a GWT RPC call into a ListStore using Sencha GXT 3.0? I know there are numerous examples of using the ModelData and BeanModel interfaces used in the 2.x versions but 3.0 does away with the need to use these interfaces and supposedly allows for POJO objects to be loaded in using classes which implement the ValueProperty interface.
I have seen the RequestFactoryBinding example and the RequestFactory Grid example in the 3.0 Explorer but those appear to demonstrate the use of a custom Data Proxy and a Receiver. I assume from reviewing the code in those examples that these techniques/classes may be required but that is not made apparent anywhere. It's possible that there is more documentation forthcoming but so far I haven't been able to find much of anything beyond that javadocs and the Explorer which lacks some of the source classes used in the example methods.
Links to both examples below.
The RequestFactoryBinding Example:
http://www.sencha.com/examples/#ExamplePlace:requestfactorybinding
RequestFactory Grid example:
http://www.sencha.com/examples/#ExamplePlace:requestfactorygrid
DataProxy and Loader are used mostly to facilitate a) relying on the server for filtering/paging/sorting, or b) reuse between parts of the application for getting access to the same pieces of data. They are not required (as in 2.x) in cases where the client only loads data once, or where manual store management is done.
The various store loading classes (ListStoreBinding, LoadResultListStoreBinding) demonstrate internally how the ListStore can be fed items. This first way allows you to replace the existing items in the store from the onSuccess method in your RPC callback or RequestFactory receiver:
List<MyData> newItems = ...;//response from server
ListStore<MyData> store = ...;//current store to replace/update
store.replaceAll(newItems);
If only loading once, or only appending, not replacing, the other method should be used:
store.addAll(newItems);
Items can be added one by one using store.add, however this will result in an event per item, and should be avoided.
Edit: Also, and this may not totally be clear coming from 2.x, but no superclass/interface is required for data itself. ValueProvider is only used as an external abstraction for how models are manipulated - how values are generically read or set from any kind of model. The PropertyAccess interface allows ValueProvider (and other) instances to be generated by just the property name that the values will be get/set from using bean accessors. ValueProvider types/instances are not required for loading data, merely for the data widgets themselves to extract the data they are displaying, and to make modifications after the user edits the values.
Knowing these pieces, the loader/proxy mechanism will be loading data in the same basic way. The Loader is responsible for being told what settings (paging, filtering, and/or sorting) to use when loading, then triggering the load - different subclasses have different responsibilities, accept different load config types, and return different results. The DataProxy then is the mechanism that actually talks to whatever holds the data, asynchronously if on a server, and informs the loader when the results are available via a callback.
The examples listed in the question both use RequestFactory, but there are several examples as well that use RPC, and a few loading from just JSON or XML. In http://www.sencha.com/examples/#ExamplePlace:paginggrid the main data loading parts are as follows:
// The rpc async instance
final ExampleServiceAsync service = GWT.create(ExampleService.class);
// As in Ext GWT 2, there is a convenience proxy for RPC to just pass the callback
// directly to the RPC call. If you need a custom callback, just be sure to invoke
// `callback.onSuccess` with the final result.
RpcProxy<PagingLoadConfig, PagingLoadResult<Post>> proxy = new RpcProxy<PagingLoadConfig, PagingLoadResult<Post>>() {
#Override
public void load(PagingLoadConfig loadConfig, AsyncCallback<PagingLoadResult<Post>> callback) {
service.getPosts(loadConfig, callback);
}
};
// ...
// The loader itself has a reference to the proxy so that loader.load() results
// in a round trip to the server, as outlined above.
final PagingLoader<PagingLoadConfig, PagingLoadResult<Post>> loader = new PagingLoader<PagingLoadConfig, PagingLoadResult<Post>>(
proxy);
loader.setRemoteSort(true);
// This last piece - instead of 2.x where the loader is a parameter to the store,
// in 3 you directly wire the results of the loader to add the items into the
// store, as discussed in the first half of this answer
loader.addLoadHandler(new LoadResultListStoreBinding<PagingLoadConfig, Post, PagingLoadResult<Post>>(store));
FWIW I spiked a GWTP Dispatch version of a remotely paged and sorted grid. Which is GWT RPC with a command pattern twist.
Assuming you're familiar with grids, you'll require an instance of:
RpcProxy
PagingLoader
LoadResultListStoreBinding
And the methods that need to be invoked:
PagingLoader.setRemoteSort(true)
PagingLoader.addLoadHandler()
Grid.setLoader()
PagingToolBar.bind()
I am trying to figure out the best way to design something. I am writing an iPhone App and for the most part I am using async calls to a web service. This means that I cam setting up a URLConnection, calling start and letting it call me back when the data is available or an exception occurs. This works well and I think is the correct way to handle things.
For example:
I request a list of people from a web service. The resulting list is Xml Person elements which will be translated into an objective-c "Person" object by my XmlDelegate.
When I call the function to get the person, I pass in a "PersonResultDelegate", which is a protocol with a single function called "PersonReceived:(Person *)p". So, each time I get a complete Person object, I call that method and all is well. So, my detail view (or search result view) just receives the elements as they are available.
The problem comes when I need to obtain more then one specific object. In my specific case, I need to get the first and last appointment for a person. So, I need to make two API calls to obtain these two single Appointment objects. Each Appointment object will result in a call to the registered AppointmentResultDelegate, but how will I know which is the first and which is the last? I also need to somehow handle the case when there is no "first" or "last" Appointments and the Delegate will never get called.
What would be the correct way design wise to handle this? Should I add some additional context information to the initial request which is passed back to the handle in the delegate? An opaque piece of data which only makes sense to the person who made the initial call? What are my other options?
Solution
What I actually ended up doing is just passing an opaque piece of data along with the Appointment to the delegate. So, when I request an appointment object I have a method like:
getNextAppointment withDelegate:self withContext:#"next"
getPrevAppointment withDelegate:self withContext:#"prev"
This way when the delegate gets called I know what appointment is being delivered.
"Each Appointment object will result in a call to the registered AppointmentResultDelegate, but how will I know which is the first and which is the last?"
By looking at the order in which you receive these callbacks. Or by looking at some value in that xml data. Like a sequence or data. I don't know your data of course.