GWT Initialize ClientBundle With Multiple CssResources - java

I'm working on updating some legacy code to GWT 2 and I'm running into some odd behaviour. I have a custom interface that extends ClientBundle as per the gwt docs. Within that bundle I define several CssResources to point to the various .css documents for my module. The problem comes when I go to actually initialize my module. I have some code in the initializer that gets the static reference to each CssResource and calls ensureInjected(). The problem is, only the first call actually does anything. Any subsequent calls seem to be getting ignored and the css styles are not getting added to the application. What do I need to do to work with multiple css documents for a single module?
CssBundle.java
public interface CssBundle extends ClientBundle {
public static final CssBundle INSTANCE = (CssBundle) GWT.create(CssBundle.class);
/* CSS */
#Source("mypath/public/Client.css")
public ClientCss mainCSS();
#Source("mypath/resources/css/mini/ext-all.css")
public ExtAllCss extAllCSS();
}
ClientCss.java
public interface ClientCss extends CssResource {
String applicationTitle();
String branding();
String bugReportDirections();
#ClassName("Caption")
String caption();
}
ExtAllCss.java
public interface ExtAllCss extends CssResource {
#ClassName("close-icon")
String closeIcon();
#ClassName("close-over")
String closeOver();
#ClassName("col-move-bottom")
String colMoveBottom();
}
MyModule.java
public class MyModule extends Composite
{
public void initialize()
{
//this css shows up in the client
CssBundle.INSTANCE.mainCSS().ensureInjected();
//this does nothing
CssBundle.INSTANCE.extAllCSS().ensureInjected();
}
}

That code looks exactly right, but might not function the way you expect - instead of each ensureInjected() causing a new <style> block to be created, instead they just enqueue the styles that they need to be made available, and at the end of the current event loop a single <style> is added with all of the various collected styles. This limits the number of times that the document potentially needs to be restyled, and also helps reduce the number of style tags (old IE had a bug where there was a max number of tags possible).
To confirm this, check the entire contents of the <style> tag, you should see that both css files are appended there, one after the other.

Related

Is there a way to delegate the implementation of an interface to a different class?

I've been working on Xamarin for the past couple of years along with Android studio and I decided to create an application for a friend (full source code here https://github.com/nekrull/waiter don't be too harsh please :) )
The idea is that there is a base activity which exchanges fragments when a new screen should appear.
Fragments have everything that has to do with user interaction and the activity they are attached to handles the business logic.
To do this I have a base class CoreActivity/DataActivity which has some methods most Fragments use (like blocking the back button) and some helper methods (like calling a method on an attached fragment of a specific class) , a CoreInteraction that responds to this activity and
CoreFragment/AttachedFragment which is used as the base of all view fragments
so for example the view fragment would look like this:
public class GroupsFragment extends AttachedFragment<GroupsFragment.GroupsInteraction> {
//this is what we expect to be able to call in the parent
public interface GroupsInteraction extends CoreInteraction {
Group get_shown_group();
void new_group();
void select_parent();
}
}
which is basically a fragment that expects its attached activity to be able to respond to the interaction methods.
the activity fragment would look like this:
public class MainActivity extends DataActivity<MainData> implements
GroupsFragment.GroupsInteraction, (other interactions here) {
}
The problem is that since the application I'm working on has only one Activity with many small screens, the code inside the base activity will get big, that does not cause a problem with the application or compiling or anything else. But it makes it really hard to find what I'm looking for easily.
What I used to do in Xamarin is something like this:
public partial class MainActivity : DataActivity<MainData> {
}
for the initialization activity and then each interaction would get its own file like this:
public partial class MainActivity : GroupsInteraction {
}
It had the same effect (since the class is compiled as a single class) but the code would be tidy and easy to read.
Obviously there are no partial classes in Java, but is there a way to delegate the implementation of an interface to another class?
Something along the lines of saying "when you're invoking a method from interface a, invoke it from that class" without actually writing stuff like :
public Group get_shown_group() {
return new GroupHandler(this).get_shown_group();
}
public void new_group() {
new GroupHandler(this).new_group();
}
public void select_parent() {
new GroupHandler(this).select_parent();
}
Thanks in advance for any help you can provide
Something along the lines of saying "when you're invoking a method from interface a, invoke it from that class"
Taking you literally what you describe is plain delegation, a class does not implement some or any functionality itself, instead it wraps a class implementing the desired functionality, calling the methods of said wrapped class. You could even switch implementation at runtime, just changing the wrapped class as you go (assuming the classes share a common interface, of course). Of course that does not "spare" you from writing the delegations yourself.
class Wrapper implements GroupsInteraction {
private final GroupInteraction gi;
public Wrapper(GroupsInteraction gi) {
this.gi = gi;
}
Group get_shown_group() {
return this.gi.get_shown_group();
}
// ... other interface impls
}
Additionally, you should keep the GroupHandler as a member instead of creating a new Object each time, so
public Group get_shown_group() {
return new GroupHandler(this).get_shown_group();
}
becomes
public Group get_shown_group() {
return this.groupHandler.get_shown_group();
}
You can try Delegation Pattern
BaseActivity {
MyDelegateClass delegate;
void example() {
delegate.example();
}
}
P.S. both activity and delegate implements same interface
Details here

final static attribute change.. any idea or approach?

I have to maintain a code to add more flexibility to a final static variable in a class.
The variable is no more a global constant and may be changed.
The problem is that the class is in a common library and used in different projects.
Do you have an approach or a design pattern better than copying and pasting the class code from the common library to my specific application and refactoring it?
Example:
Commons project
Class CommonClass {
public final static var globalSomething = somethingGlobal;
public static method(){ //CommonClass.globalSomething is used here}
}
In my App (and other apps that reference commons) we can use the static attribute and also call the method:
---> var b = CommonClass.somethingGlobal;
---> var c = CommonClass.method() //we know that CommonClass.globalSomething is used here
Expectations:
Ability to change CommonClass.somethingGlobal in my app and take these changes in call CommonClass.method()
I can modify (add methods) in the common class but i have to keep the same initial behavior (not to break other project referencing common project)
If I got you right, you want to implement this as a parameter.
Looking at your example:
var c = CommonClass.method() //we know that CommonClass.globalSomething is used here
there is already something wrong with it. You shouldn't have to know that you have to set CommonClass.somethingGlobal correctly before calling the method. This way the client has to know the implementation, violating the principle of information hiding. If the value is required, introduce it as parameter:
Class CommonClass {
public static void method(var globalSomething){}
}
An alternative would be making both your variable and your method non-static and use a constructor:
Class CommonClass {
public var globalSomething = somethingGlobal;
public CommonClass(var globalSomething) {
this.globalSomething = globalSomething;
}
public void method(){}
}
PS: Your example code is not java. I corrected it partially in my answer.

how to register a java class if the static initializer isn't called till the class is referenced

I've an interface implemented by classes that perform a file processing, say searching or whatever.
public interface FileProcessorInterface {
public void processFile(String fileName);
}
Then i have a different implementation for each file type:
public class TxtProcessor implements FileProcessorInterface {
#Override public void processFile(String fileName) { //do the work }
}
Thus i have the Utilizer of the processor, that has a method that allows for registering each class, something like this:
class Utilizer {
Map <String, Class> registered = new HashMap<>();
public void registerClass(String fileExt, Class clazz) {
registered.put(fileExt, clazz);
}
public void processFile(String fileName) {
//1) get the registered class from registered map (omitted because easy and not relevant)
//2) create an instance of the class using reflection (omitted because easy and not relevant)
FileProcessorInterface p = ....
p.processFile(fileName);
}
So far it's ok.
Now, i'm providing many implementations of my interface.
And i am tempted to provide each implementation class with a static initializer that register itself in the Utilizer, in the case of my previous TxtProcessor it would be:
class TxtProcessor implements FileProcessorInterface {
//previous code
static {
Utilizer.registerClass("txt", TxtProcessor.class);
}
}
The problem is that this static method will never be called because in the "statically reachable" code of the application there is no reference to my TxtProcessor class, since it is instantiated via reflection. So the jvm does not call the static initializer.
Say that i have two parts: the "generic code" that is the Utilizer and on the other side the implementations; it has to be thought as something provided dinamically and so it is not known by the Utilizer part.
Infact the idea was exactly that each class would register itself leaving the Utilizer untouched.
It is hard for me conceiving a solution that does not put some form of 'knowledge' of the implementations on the Utilizer side (and that stays simple), just because of the problem of the static initializer not called. How to overcome this?
Using reflections seems to be the best fit here. It's like geared to do this.
All you need is a small static block in Utilizer as
static {
Reflections reflections = new Reflections(
new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage("path.to.all.processors.pkg"))
.setScanners(new SubTypesScanner())
);
reflections.getSubTypesOf(path.to.all.processors.pkg.FileProcessor.class);
}
If you don't want a third-part dependency, just add a FileProcessors.properties file to your classpath
txt=path.to.all.processors.pkg.TxtProcessor
doc=path.to.all.processors.pkg.DocProcessor
pdf=path.to.all.processors.pkg.PdfProcessor
and then register all the listed classes from Utilizer as
static {
Properties processors = new Properties();
try {
processors.load(Utilizer.class
.getResourceAsStream("FileProcessors.properties"));
} catch (IOException e) {
e.printStackTrace();
}
for (String ext : processors.stringPropertyNames()) {
Utilizer.registerClass(ext, Class.forName(processors.getProperty(ext));
}
}
This no longer requires a static block in every FileProcessor now.
You can look at Reflections library. It allow you to find all the classes which implement an interface, have an annotation or extend a class.
You Could...
Use the same concept as JDBC does for loading it's drivers. This would require you to use Class#forName to initialize the class when the program is first loaded. While this does mean that the implementation is still dynamic from the point of view of your utility class, it is specified at run time by your application...
This gives you control over which implementation you might want to use
You Could...
Use the same concept as something like java.awt.Toolkit uses when it initializes it's instance.
It basically looks up the resource (in this case a System property) and then loads the class dynamically using Class.
Personally, I normally look for a named resource (usually a properties file) and load a key from it.
Something like getClass().getResource("/some/gloabl/configFile");, which every implementation would need to provide.
Then, if available, read the properties file and find the key I'm after.
If more then one implementation is linked in though, there is no guarantee which one will be loaded.
Quick and dirty: You can statically initialize your Utilizer in main() with correct association.
Better solution: externalize in a resource file association like
txt=path.to.package.TxProcessor
load it in Utilizer and load FileProcessorInterface implementors with Class.forName()
you can force the static init by Class.forName(fqn, true, classLoader) or the short form Class.forName(fqn)
You could have a registry file (for example, some XML file), that would contain the list of all classes you support :
<item type="txt">somepackage.TxtProcessor</item>
<item type="gif">somepackage.GIFProcessor</item>
...
Your Utilizer would load this file into its registry.

Wicket head section hierarchy

I am a little confused about tags. I know from wicket 1.5 there was a change of head render strategy from parent->child to child->parent.
Now I use wicket 6.9 and I have simple menu panel which I want to use some jquery effects.
I want to use the same jquery (for example for google) file for whole application.
I cannot use jquery link only in main page, because in while rendering menu panel there is " $(document).ready" and it is not recognized. Reading some forum i found opinion that panel should contain jquery itselft - it is reasonable, because it can be reusable independently.
So now my page consist:
<head>
...
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
...
</head>
And my menu panel consist the same. As a result in rendered html I load jquery.js twice.
How should I resolve it? I want to load it only once. I know i can back to old strategy and do application.getResourcesSettings().setHeaderItemComparator() but as i read it is not the best solution.
I can found such class like PriorityHeaderItem in wicket, but documentation is very poor for wicket and did not found any example of use it.
Best regards
Since wicket 1.6 jQuery is now the javascript library used by the framework. So you may see jQuery twice because of the one you included and the wicket version? If you want to override the jQuery version you can create a Resource Reference and then set it in your init method of the Application class.
First you need the resource reference file and put the js file in same package structure.
public final class JQueryResourceReference extends JavaScriptResourceReference {
private static final JQueryResourceReference INSTANCE = new JQueryResourceReference();
private JQueryResourceReference() {
super(JQueryResourceReference.class, "jquery.js");
}
public static JQueryResourceReference get() {
return INSTANCE;
}
}
Then in the application init method do this:
public MyApplication extends AuthenticatedWebApplication {
#Override
protected void init() {
super.init();
getJavaScriptLibrarySettings().setJQueryReference(JQueryResourceReference.get());
....
}
....
}

GWT app UI wont display

I have implemented a simple GWT app that uses 1 Place and 1 Activity (which I have implemented as a Presenter which extends an AbstractActivity and which contains a Composite "view" subclass). The 1 and only UI object in the view is a GWT-Bootstrap NavBar that I want presented at the very top of my "home page".
I'm running the app locally from inside Eclipse and am not getting any compiler or runtime errors. When I go to the URL that the Development Mode console points me to, I get a slight pause in the browser (I assume this is the browser "downloading" the JavaScript) and then I see a blank white screen (instead of my NavBar). The window title is correct (I set this in the module's HTML page) and when I view source I see the same HTML source, so I know that the app's JavaScript is getting to the browser properly. It's just not rendering the NavBar.
I have sprinkled System.out.println() statements throughout onModuleLoad(), my default ActivityManager, ActivityMapper, PlaceHistoryMapper, presenter and view Composite, and all these sysout statements print in the dev console; telling me that I have wired everything together correctly, and that at runtime when the PlaceHistoryHandler#handleCurrentHistory method is called (from inside onModuleLoad), I should be seeing my NavBar.
The only possibilities I can think of are:
I have configured gwt-bootstrap incorrectly; or
I'm not using UiBinder correctly
Something else is wrong with how I am using Activities and Places, or perhaps how I am attaching the UI to RootLayoutPanel inside onModuleLoad().
As for gwt-bootstrap:
I placed the JAR on my project's classpath (I know this because when I include a new UiField of type NavBar inside my widget/view, I don't get any compiler errors)
I added <inherits name="com.github.gwtbootstrap.Bootstrap"/> to my GWT module XML
So if there's anything else I have to configure, please let me know!
As for the UiBinder stuff, here's my widget/view:
public class WebRootDisplay extends BaseDisplay {
private static WebRootDisplayUiBinder uiBinder = GWT
.create(WebRootDisplayUiBinder.class);
interface WebRootDisplayUiBinder extends UiBinder<Widget, WebRootDisplay> {
}
#UiField
Navbar navBar;
public WebRootDisplay(EventBus eventBus) {
super(eventBus);
System.out.println("I get this printing to the console at runtime.");
initWidget(uiBinder.createAndBindUi(this));
System.out.println("...and this too!");
}
}
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<g:HTMLPanel>
<b:Navbar ui:field="navBar">
<b:Nav>
<b:NavLink href="http://www.google.com">
Home
</b:NavLink>
</b:Nav>
</b:Navbar>
</g:HTMLPanel>
</ui:UiBinder>
One thing I noticed is that I've got my NavBar inside an HTMLPanel in the UiBinder XML. I did this because I used the Google-Eclipse plugin to generate a new UiBinder for me (which autogenerated both the Composite (which I then modified to extend BaseDisplay, which itself extends Composite) as well as the UiBinder snippet. I figured GWT wants me to put all the UI fields inside this HTMLPanel...(?)
If I'm missing anything here please let me know. I'm not instantiating the NavBar field because I believe that's what createAndBindUi does for me.
If both my gwt-bootstrap config and my use of UiBinder looks correct, then something else is obviously wrong and I will have to post more code. I just wanted to hold off on that initially before these first two items were ruled out. Thanks in advance!
Update
Here is onModuleLoad:
public void onModuleLoad() {
// Some homegrown DI stuff. I have verified that the injector works properly.
ApplicationScope appScope = new ApplicationScope();
setInjector(new ApplicationInjector(appScope,
InjectorProvider.newMasterProvider()));
// Add the sole composite child to the RootLayoutPanel.
// I have verified that injectWebRootDisplay returns a fully configured
// WebRootDisplay instance.
RootLayoutPanel.get().add(injector.injectWebRootDisplay());
historyHandler.register(placeController, eventBus, defaultPlace);
historyHandler.handleCurrentHistory();
}
Could you paste the onModuleLoad() part of your code please?
If you don't got any Exception and error message, I think you should check that you add the view properly to the RootPanel, or when you run the app you should check that the view is there in a div in the HTML and just unvisible or something similar.
The UiBinder part looks fine in a first look.
EDIT:
This onModuleLoad() doesn't said too much to me, but you could try something.
I always use the RootLayoutPanel.get() method in the following way:
RootLayoutPanel.get("someDivId").add(injector.injectWebRootDisplay());
So I always add a div or table to the placeholder HTML with a id, so you can refer to that div when you get the RootPanel. I'm not confident about this is necessary, but I saw this at the first time, and it's working properly.
If you have question or problem, please let me know. :)
Well, I've tried a local example looking exactly like yours code, and I think that problem is not in UI binder. The code you provided so far, is correct, so it most likely that the error is somewhere else.
The biggest suspect is the BaseDisplay class. As far as I can see, this class is not from GWT or gwt-bootstrap. You can really quickly check it, by changing WebRootDisplay class, so it extends classic GWT Composite class instead of BaseDisplay (and disabling all mvp stuff for while). If it works, you have a proof that the problem is caused by 'BaseDisplay'
Since I don't have the full code, I can only assume that WebRootDisplay is used also for displaying the views, and most likely the error is that when view is added to that class, previously added widget (in your case it is a NavBar which you add in constructor of WebRootDisplay) is removed. Most likely the problem should be in methods setWidget and initWidget
In my experience with GWT Activities and Places, a common culprit of a blank white page is failing to register the Place's Tokenizer with the PlaceHistoryMapper as so:
/**
* PlaceHistoryMapper interface is used to attach all places which the
* PlaceHistoryHandler should be aware of. This is done via the #WithTokenizers
* annotation or by extending PlaceHistoryMapperWithFactory and creating a
* separate TokenizerFactory.
*/
#WithTokenizers({
MyPlace.Tokenizer.class,
SomeOtherPlace.Tokenizer.class})
public interface AppPlaceHistoryMapper extends PlaceHistoryMapper {}
See https://developers.google.com/web-toolkit/doc/latest/DevGuideMvpActivitiesAndPlaces#PlaceHistoryMapper
Another cause for a white page (particularly when using RootLayoutPanel.get() with a single place is failing to map the place correctly in the ActivityMapper:
/**
* AppActivityMapper associates each Place with its corresponding
* {#link Activity}
*
* #param clientFactory
* Factory to be passed to activities
*/
public class AppActivityMapper implements ActivityMapper {
private ClientFactory clientFactory;
public AppActivityMapper(ClientFactory clientFactory) {
super();
this.clientFactory = clientFactory;
}
#Override
public Activity getActivity(Place place) {
if (place instanceof MyPlace)
return new MyActivity((MyPlace) place, clientFactory);
else if (place instanceof SomeOtherPlace)
return new SomeOtherActivity((SomeOtherPlace) place, clientFactory);
return null; // If your return null with single place bound to RootLayoutPanel
// you may get a blank white page
}
}
See https://developers.google.com/web-toolkit/doc/latest/DevGuideMvpActivitiesAndPlaces#ActivityMapper
Without a more complete code sample it is impossible to determine exactly what is happening, but the two causes outlined above are common oversights which may help anyone who comes across this thread.
Instead of System.println use GWT.log messages. Then open the Javascript console (of Firebug or Chrome) and see where your code ends up. GWT.log will print out in the browser console, so you can see what the compiled JS code does.
Also, if you compile with the Pretty mode, you'll see the generated Javascript code in the browser and be able to step through and see what is being called (or not).

Categories