My online tech scrapbook where I keep my notes in case I need to look them up later
Showing posts with label wicket. Show all posts
Showing posts with label wicket. Show all posts
Monday, September 10, 2012
Wicket Multiple Choice Select Box
The component to use for this is the ListMultipleChoice class.
Tuesday, July 10, 2012
Apache Wicket: AjaxSubmitLink No Response
What happens is when you click the AjaxSubmitLink, there is no response, no error messages, and you don't know why there is a problem.
This is potentially a gotcha caused by "setRequired(true)" in your form elements. The form will refuse to act (and won't tell you why) when you leave a required field blank.
This is potentially a gotcha caused by "setRequired(true)" in your form elements. The form will refuse to act (and won't tell you why) when you leave a required field blank.
Friday, June 1, 2012
Wicket Feedback Panel
Convenient way of adding feedback messages.
In each component, just call info(), debug(), warn(), error() to send messages to the FeedbackPanel
In each component, just call info(), debug(), warn(), error() to send messages to the FeedbackPanel
Wicket Request Cycle Customization
There are times where you'd need to add some custom logic in the Request Cycle itself. One example is when your site has single-sign-on integration with other sites. What that means is that you'd have to check the validity of the session from time to time.
Putting this checking logic in the Page class (or a general super-class Page) is not the answer, as you'd need to also perform these checks for Ajax requests that don't load a new page. The best way to do it is to add this logic into the Request Cycle.
In Wicket 1.5, the Request Cycle API as changed. To add some logic to the Request Cycle, create a concrete implementation of AbstractRequestCycleListener, and then add it from the Application object.
protected void init() {
getRequestCycleListeners().add(new YourCustomizedRequestCycleListener());
}
In YourCustomizedRequestCycleListener, override 2 methods:
Putting this checking logic in the Page class (or a general super-class Page) is not the answer, as you'd need to also perform these checks for Ajax requests that don't load a new page. The best way to do it is to add this logic into the Request Cycle.
In Wicket 1.5, the Request Cycle API as changed. To add some logic to the Request Cycle, create a concrete implementation of AbstractRequestCycleListener, and then add it from the Application object.
protected void init() {
getRequestCycleListeners().add(new YourCustomizedRequestCycleListener());
}
In YourCustomizedRequestCycleListener,
- onRequestHandlerResolved:
- The request cycle listener callbacks are called for all kinds of requests, including requests for CSS files and Images, by putting the session logic here, you'll be able to differentiate between Page / Ajax requests and other requests)
- Page requests: Test handler to be of class RenderPageRequestHandler
- Additionally, you may even need to check to exclude certain pages (e.g. public pages, error pages). Get the page class using this: ((RenderPageRequestHandler)handler).getP
ageProvider().getPageClass()) - Ajax requests: Test handler to be of class ListenerInterfaceRequestHandler (which may also include non-Ajax requests but we want to include them too)
- onException (if you need to send users to an error page, throw an exception inside onRequestHandlerResolved and handle it here)
- To send user to error page: return new RenderPageRequestHandler(new PageProvider(ErrorPage.class));
Notes: This seems to be quite a lot of work to do something that's actually a pretty common requirement. Maybe there can be an easier way to do it. In any case, this works.
Data Table Component in Wicket
Wicket provides a Data Table component that can be easily reused to create data tables.
References:
- Use the class AjaxFallbackDefaultDataTable
- Define the columns by creating them one-by-one and adding them to the Data Table
- This can be an AbstractColumn where you provide the component to use inside the cell
- Or a PropertyColumn where the cell shows data bound to a model
- Also provide a database provider implementing SortableDataProvider
- Within the provider, implement iterator, size, and model methods
- The table can be styled via CSS that you provide
References:
Making Wicket Log to Log4J
Just add file slf4j-log4j12-1.6.4.jar (other versions will probably work too) to the classpath of the web-app.
Download file from: http://www.slf4j.org/download.html
Download file from: http://www.slf4j.org/download.html
Table Cell Background Image in Wicket
HTML code for TD background image:
<td style="background-image: url(abc.png); background-repeat: no-repeat;">
Wicket code for generating this code:
First step is to obtain the URL of the background image. Let's say this time the image is in the package (i.e. together with the Java & HTML classes for a more object-oriented approach).
imageUrl is the relative path from the context root to the image file. However, this URL will not work as-is, as the current page is unlikely to be on the context root.
To generate full URL:
imageUrl = RequestCycle.get().getRequest().getConte xtPath() + "/" +imageUrl;
getContextPath is new in Wicket 1.5.
Lastly, create the style attribute with an AttributeModifier.
tdElement.add(new AttributeModifi er("style", "background-ima ge:url("+imageU rl+");backgroun d-repeat: no-repeat;"));
<td style="background-image: url(abc.png); background-repeat: no-repeat;">
Wicket code for generating this code:
First step is to obtain the URL of the background image. Let's say this time the image is in the package (i.e. together with the Java & HTML classes for a more object-oriented approach).
PackageResourceReference bgImageResource = new PackageResourceReference(this.getClass() ,"abc.png");
String imageUrl = RequestCycle.get().urlFor(bgImageResourc e, new PageParameters()).toString();
imageUrl is the relative path from the context root to the image file. However, this URL will not work as-is, as the current page is unlikely to be on the context root.
To generate full URL:
imageUrl = RequestCycle.get().getRequest().getConte
Lastly, create the style attribute with an AttributeModifier.
tdElement.add(new AttributeModifi
Wicket: Running Javascript On Client-Side Before Submitting Data to Server
In Wicket, we usually depend on the server-side logic to perform AJAX updates on the page. However, that's not always practical. It could be because of performance reasons, or in the case of file uploads, a limitation of the Wicket framework. For the latter, it's because no AJAX updates via Wicket is possible until the file upload is completed. If for example I wish to hide the upload button immediately on submission, that can't be done via Wicket's AJAX.
To achieve this, we can use an AttributeModifier to prepend Javascript to e.g. the "onchange" attribute of the file upload input element.
To achieve this, we can use an AttributeModifier to prepend Javascript to e.g. the "onchange" attribute of the file upload input element.
fileUploadField.add(new AjaxFormSubmitBehavior(this,"onchange") {
// ----- implementation snipped ----------
});
fileUploadField.add(AttributeModifier.prepend("onchange", "this.style.visibility='hidden';"));
// ----- implementation snipped ----------
});
fileUploadField.add(AttributeModifier.prepend("onchange", "this.style.visibility='hidden';"));
Java Generics: Void
Use Void when the class type in the generics is not relevant for the situation.
For example, in Wicket's AjaxLink, it doesn't always have a model. In that case we can use AjaxLink<Void>.
For example, in Wicket's AjaxLink, it doesn't always have a model. In that case we can use AjaxLink<Void>.
Brix CMS for Wicket
The main problem with almost all the CMS out there is that they are optimized for building websites. They are not optimized for building web-apps. In fact, for some of the most popular ones (e.g. Drupal, Joomla), they require software engineers to commit to huge compromises when they want to build a web-app. Why should software engineers have to compromise just because they need CMS functionality? That's a question I've always been asking.
My favorite web application development framework is Apache Wicket, which allows web applications to be built in a truly object oriented manner, and all I need for some of my projects is to be able to build a web-application with some CMS capabilities without having to go slumming with PHP or do some crazy hacks to integrate a CMS with the web-app. I'm just so sick of all the "our way or the highway" (The "Drupal Way" *rolleyes*) approach to developing web-app functionality into CMSes.
Brix CMS claims which I like and find promising:
Links:
My favorite web application development framework is Apache Wicket, which allows web applications to be built in a truly object oriented manner, and all I need for some of my projects is to be able to build a web-application with some CMS capabilities without having to go slumming with PHP or do some crazy hacks to integrate a CMS with the web-app. I'm just so sick of all the "our way or the highway" (The "Drupal Way" *rolleyes*) approach to developing web-app functionality into CMSes.
Brix CMS claims which I like and find promising:
- "Most CMS are for building web sites. Brix CMS is for building web applications."
- "BRIX is not a standalone CMS, but rather a CMS framework which allows for easy integration of CMS functionality into existing Wicket-based applications."
Links:
Removing the "Choose One" Option From Wicket's DropDownChoice
It's a bit of a hack how to do this. Basically it involves triggering some convention by:
- Extend the DropDownChoice class
- Add the following code to override a method:
@Override
protected CharSequence getDefaultChoice(Object arg0) {
return "";
}
Wicket Modal Window Form Issue
Wicket has a strange problem with forms that requires a work-around. It says in the Javadoc of ModalWindow:
"If you want to use form in modal window component make sure that you put the modal window itself in another form (nesting forms is legal in Wicket)"
If this is not done, when using Firefox, form submissions may not be successful.
It appears that this issue exists due to backward compatibility constraints with IE6.
In order to work around this, it is required to put the modal window in another form, like this:
<form wicket:id="modalWindowForm">
<div wicket:id="modalWindow"></div>
</form>
References:
"If you want to use form in modal window component make sure that you put the modal window itself in another form (nesting forms is legal in Wicket)"
If this is not done, when using Firefox, form submissions may not be successful.
It appears that this issue exists due to backward compatibility constraints with IE6.
In order to work around this, it is required to put the modal window in another form, like this:
<form wicket:id="modalWindowForm">
<div wicket:id="modalWindow"></div>
</form>
References:
- wicket.apache.org/apidocs/1.4/org/apache/w
icket/extensions/ajax/markup/html/modal/M odalWindow.html - issues.apache.org/jira/browse/WICKET-314
6 - issues.apache.org/jira/browse/WICKET-340
4 - www.techienuggets.com/Comments
- apache-wicket.1842946.n4.nabble.com/Form-t
ag-does-not-get-rendered-on-a-Panel-plac ed-in-a-TabbedPanel-within-a-ModalWindow-t d1887897.html - issues.apache.org/jira/browse/WICKET-221
4 - web.archiveorange.com/archive/v/yH01cYmi
I4SdLFnAfqjy
Building a Wicket Component Which Updates Itself When the Model Changes
For a component to update itself when model is updated:
- Implement a method (e.g. update) that updates the UI components. This can be called from:
- the constructor and
- whenever the model is changed.
- Override the onModelChanged method, like this:
@Override
protected void onModelChanged() {
protected void onModelChanged() {
super.onModelChanged();
update();
update();
}
- onModelChanged will be automatically called by Wicket IF the reference of the Model Object has changed. Deep changes (e.g. changes in one of its fields) will not be detected.
- So in order for onModelChanged be called, either:
- replace the Model Object with a modified clone (in which case Wicket will automatically call it) OR
- call onModelChanging & onModelChanged manually.
- Ensure that the Component is added to an AjaxRequestTarget and it will be updated via AJAX automatically
Wicket Handling JavaScript Events
Wicket provides useful classes for handling of JavaScript events such as:
p
To handle a JavaScript event e.g. onMouseOver on an element on the page hierarchy, add the following:
add(new AjaxEventBehavior("onMouseOver") {
protected void onEvent(AjaxRequestTarget target) {
// do something.....
}
}
);
AjaxFormSubmitBehavior can be used in a similar way to achieve the same results when it is necessary to capture information for processing (e.g. real time search)
Also note that for very chatty Ajax events like onKeyUp & onKeyDown, setThrottleDelay can be used.
- onMouseOver
- onMouseOut
- onFocus
- onBlur
- onKeyUp
- onKeyDown
- etc.
To handle a JavaScript event e.g. onMouseOver on an element on the page hierarchy, add the following:
add(new AjaxEventBehavior("onMouseOver")
protected void onEvent(AjaxRequestTarget target) {
// do something.....
}
}
);
AjaxFormSubmitBehavior can be used in a similar way to achieve the same results when it is necessary to capture information for processing (e.g. real time search)
Also note that for very chatty Ajax events like onKeyUp & onKeyDown, setThrottleDelay can be used.
Working with CSS & JS Files in Wicket
In Wicket, the preferred choice of serving CSS/JS files is as a resource from the JAR instead of from a physical file inside the web folder. The API provides an easy way to get it done that also comes with a lot of flexibility & modularity.
Basically you can call from anywhere in your Java code:
This also means that at the Page class level, you can choose to either use the CSS file provided by the component, or override and add your own instead.
Also, there is an option to provide a location instead (the more traditional way for web-apps) with the "getHeaderContribution" method.
Reference: Wicket WIKI
Basically you can call from anywhere in your Java code:
- add(CSSPackageResource.getHeaderContribu
tion(NiceButton.class, "button.css"));
- add(JavascriptPackageResource.getHeaderC
ontribution(SomePanel.class, "panel.js"));
This also means that at the Page class level, you can choose to either use the CSS file provided by the component, or override and add your own instead.
Also, there is an option to provide a location instead (the more traditional way for web-apps) with the "getHeaderContribution" method.
Reference: Wicket WIKI
Wicket Replace Page Title with AJAX
In Wicket, trying to make the page title a Label backed by a property model & trying to change the title by changing the underlying property during an AJAX request by will result in a JavaScript bug in IE.
The way to change the title dynamically via AJAX that works across browsers is to append JavaScript to the AJAXRequestTarget e.g.:
target.appendJavascript("document.title= '"+newTitle+"'");
The way to change the title dynamically via AJAX that works across browsers is to append JavaScript to the AJAXRequestTarget e.g.:
target.appendJavascript("document.title=
Wicket Images Without Using Resource Streams
Wicket's Image object is based on resource streams which is different from more traditional ways of handling images. For more "traditional" ways of handling images, the following options are available:
Wicket i18n
Wicket's default i18n implementation is component based. It will look for a properties file matching the component and then outward from there.
References:
getResourceSettings().addStringResourceL oader(new CustomStringResourceLoader());
where CustomStringResourceLoader is a concrete custom implementation of IStringResourceLoader.
Reference:
References:
- cwiki.apache.org/WICKET/i18n-and-resourc
e-bundles.html - day-to-day-stuff.blogspot.com/2008/05/wi
cket-internationalization.html - www.informit.com/guides/content.aspx
getResourceSettings().addStringResourceL
where CustomStringResourceLoader is a concrete custom implementation of IStringResourceLoader.
Reference:
Wicket: Access Servlet Session & Page Redirection
Access Servlet Session
This is sometimes necessary when Wicket pages need to co-exist with servlet based ones.
((WebRequest)getRequest()).getHttpServle tRequest().getSession();
Page Redirection
getRequestCycle().setRequestTarget(new RedirectRequestTarget("home.jsp"));
This is sometimes necessary when Wicket pages need to co-exist with servlet based ones.
((WebRequest)getRequest()).getHttpServle
Page Redirection
getRequestCycle().setRequestTarget(new RedirectRequestTarget("home.jsp"));
Wicket on Google App Engine
According to this blog post, it can be done pretty easily.
Of course the persistence limitation (i.e. no filesystem, have to use Google's DB) still stand.
Of course the persistence limitation (i.e. no filesystem, have to use Google's DB) still stand.
Subscribe to:
Posts (Atom)