Let's consider the case:
Wicket page contains several components and rendering of one of them fails with some common runtime exception (like NullPointerException).
The result I see by default is: the whole page fails to render.
How to recover from this error in Wicket? What should be done, not render or replace the failing component only?
A custom IRequestCycleListener is the solution you are looking for. Read Carl-Eric's answer here:
How to handle exceptions thrown in Wicket custom model?
In a "classical" wicket application where pages and components are instantiated by code in constructors and initializers you probably have to add try-catch blocks manually to each and every possible constructor call. Wicket is not a managed framework, meaning there isn't a central component factory that could be decorated by such functionality. That does not mean though that you can't create such a component factory yourself.
In a CMS-like application we've been developing since 2006 all wicket components are instantiated by builders that themselves are created from xml or json documents (so the full layout and configuration of the app is externalized and the wicket components are just small building boxes that can be mixed and matched together like lego pieces) - so I know such an approach works and performs well. In our case each builder method that creates a component has a try-catch block that creates an empty Label instead if any RuntimeException happens.
This is weird requirement, in my humble opinion.
What is the rendering of the replacement component fails too ? Add extra logic ?! Or let it fail with stack overflow error ?
What if half of the components in the page fail ? You will show half page with proper content and the other with "Oopsies" ?!
If there is an error then it should be fixed!
Related
I could do with some help once again...
We built our own forms in XPages. Forms are defined by a user in Notes, and they are used through XPages/web. We added several managed beans to get more grip on the data used by the page and controls that are on it. The whole thing is heavily nested, the form control can be used more than once on a page, repeat controls are used as well, and now I need to partially refresh a panel.
Some of the code:
<xp:panel id="ccAnyForm">
<xp:this.dataContexts>
<xp:dataContext var="formulaire">
<xp:this.value><![CDATA[#{javascript:compositeData.formName || compositeData.dataSource.getItemValueString("Formulaire")}]]></xp:this.value>
</xp:dataContext>
<xp:dataContext var="formdata">
<xp:this.value><![CDATA[#{javascript:PageData.getForm(formulaire, compositeData.dataSource)}]]></xp:this.value>
</xp:dataContext>
</xp:this.dataContexts>
<xp:panel id="aFormulaire${javascript:compositeData.name}">
<xe:switchFacet id="switchFacet1">
<xe:this.selectedFacet><![CDATA[#{javascript:formdata.isTabbed()? "tabbed": "flat"}]]></xe:this.selectedFacet>
PageData is a Java bean, and I lose formdata when doing a partial refresh. If I set partial execution mode in the EventHandler (data validation is disabled), I get the error that says formdata not found on the last line of the snippet. If I clear partial execution mode, I get nothing at all: no error, no Java error, no SSJS error, nothing.
It must be my lack of understanding the life-cycle of objects and variables, for I prbably have to use ValueBindings or so, but I don't know how.
Help...
I've seen dataContexts recalculate as null, particularly when dependent on other dataContexts. I think in Apply Request Values phase. When I had that I changed the code to only calculate in Render Response phase.
However, I don't think that work for you, because the Switch control will need the value before Render Response, and there's no easy way to get hold of which other phase is running.
The approach I'd take is to have a property in your bean (e.g. showTabbed) that holds which Switch facet to show. Call a bean method to set that property on page load. Then in your partial refresh, call the method again, checking whether the Formulaire field has changed to determine whether or not to call setShowTabbed(boolean) again. That will minimise the number of calls even more and should prevent the problem.
In Stuts2 I am using Tiles plugin to create a layout for the website (menu, footer, header etc.) that is consistent on every page.
Now each tile is just a static HTML content.
Is it possible to make a Tile more dynamic by eg. calling a Footer action class every time the footer is to be rendered? For example: to fetch footer content from database.
If I was to do that inside every page's action class in my application this would make for a very unusable code...
So maybe it is possible from Tile perspective?
There is only one way to do what you ask with a tiles version less than 2.2.2 and that is with a "preparer".
This however is not an integration with struts2 but would mean the preparer it self will access the service layer to get the required content for the view and all that content would need to be set though tiles attributes.
With tiles versions 2.2.2 and higher:
You can use OGNL expressions within tiles attributes, this can allow access to some struts2 interaction as well as static method access. With static method access you can call a method to return a string how ever you want. Creating such a string would be on par with writing a scriptlet.
To upgrade you need to either manually override some jars to get tiles 2.2.2, or to get version three you will need to implement your own result type: How to integrate Struts 2 with Tiles 3.
I don't actually recommend either of the above methods at this time, tiles 3 is recommended but not as an excuse to do something as bad as writing a scriptlet. It would probably be better to use the s:action tag in a tile, as mentioned by David or use an Ajax method as mentioned by Jaiwo99. The reason being that both these methods keep with struts2 while the ones I presented would be unusual and be harder to maintain. Personally I would lean towards the ajax methods.
Struts2 along with the struts2-json-plugin makes creating json services very simple. Tiles is a nice system for reducing boiler plate. If ajax is used heavily the two really can compliment each other. You can make a lot of reusable ajax components, just be sure to not hard code the urls of actions. Always use the s:url tag and assign that to JS variables.
Try following code:
$('#footer').load('your/action/with/namespace');
i'm assuming your footer is with id footer, everytime you open a page, your footer action class will be called and the data can be fetched dynamically.
We use the NetBeans GUI builder to create our visual forms.
We try to make them JavaBean compliant so that we can just drag and drop components onto the screen.
However sometimes this becomes difficult as the component needs to connect to a service that is not available to NetBeans at preview/design time and thus throws an exception and stops you from dragging and dropping the component onto the form.
As a work around I've added try catches around the connections to the services that I know will fail when NetBeans tries to instantiate the form so that it can be previewed.
This feels rather hackish though, I would prefer it if there was a way to check if the component is in design mode and if that is the case then just not instatiate the objects that will throw exceptions.
Anybody got any ideas as to how I can achieve this?
It sounds like you have too much logic built into your form classes. You should consider taking all of that code that connects to your services and bundle it into one or more classes, and then inject those classes into your form at runtime. Then, make sure that the code that calls that object doesn't throw null pointer exceptions if that object is unavailable, as it would be in preview.
I'm interested in the Tapestry framework put have some problems with it due to several reasons:
The output I have to generate has to be XML. According to http://tapestry.apache.org/content-type-and-markup.html this is no big deal.
But when it comes down to use actionlink, components or all the other Tapestry goodies, the resulting code should not be anchor or div but some custom xml elements/attributes.
Is it possible to archieve this without alot of pain?
Workarounds or insides to the background mechanismn of Tapestry are welcome.
while actionlink will always render as an anchor (a) tag, the Any component can render as any arbitrary xml element, and it and many other tapestry components will render arbitrary (informal) parameters depending on their definition.
for example, (assuming you have a java method called 'getTheTime' in your class, mine returns System.currentTimeMillis())
<xyz t:type="actionlink" t:id="someaction">
a element</xyz>
<xyz t:type="any"
attribute1="${theTime}"
attribute2="prop:theTime"
attribute3="theTime">
xyz element</xyz>
will render as:
a element
<xyz attribute1="1338418847753" attribute2="1338418847753"
attribute3="theTime">xyz element</xyz>
In order to get a combination of the two, you will need to roll your own component. This is pretty simple once you understand tapestry a little better.
Have a look at the source of ActionLink.java (and its super classes) and you should be able to figure it out.
There are a couple of things that I am having a difficult time understanding with regards to developing custom components in JSF. For the purposes of these questions, you can assume that all of the custom controls are using valuebindings/expressions (not literal bindings), but I'm interested in explanations on them as well.
Where do I set the value for the valuebinding? Is this supposed to happen in decode? Or should decode do something else and then have the value set in encodeBegin?
Read from the Value Binding - When do I read data from the valuebinding vs. reading it from submittedvalue and putting it into the valuebinding?
When are action listeners on forms called in relation to all of this? The JSF lifecycle pages all mention events happening at various steps, but its not completely clear to me when just a simple listener for a commandbutton is being called
I've tried a few combinations, but always end up with hard to find bugs that I believe are coming from basic misunderstandings of the event lifecycle.
There is a pretty good diagram in the JSF specification that shows the request lifecycle - essential for understanding this stuff.
The steps are:
Restore View. The UIComponent tree is rebuilt.
Apply Request Values. Editable components should implement EditableValueHolder. This phase walks the component tree and calls the processDecodes methods. If the component isn't something complex like a UIData, it won't do much except call its own decode method. The decode method doesn't do much except find its renderer and invokes its decode method, passing itself as an argument. It is the renderer's job to get any submitted value and set it via setSubmittedValue.
Process Validations. This phase calls processValidators which will call validate. The validate method takes the submitted value, converts it with any converters, validates it with any validators and (assuming the data passes those tests) calls setValue. This will store the value as a local variable. While this local variable is not null, it will be returned and not the value from the value binding for any calls to getValue.
Update Model Values. This phase calls processUpdates. In an input component, this will call updateModel which will get the ValueExpression and invoke it to set the value on the model.
Invoke Application. Button event listeners and so on will be invoked here (as will navigation if memory serves).
Render Response. The tree is rendered via the renderers and the state saved.
If any of these phases fail (e.g. a value is invalid), the lifecycle skips to Render Response.
Various events can be fired after most of these phases, invoking listeners as appropriate (like value change listeners after Process Validations).
This is a somewhat simplified version of events. Refer to the specification for more details.
I would question why you are writing your own UIComponent. This is a non-trivial task and a deep understanding of the JSF architecture is required to get it right. If you need a custom control, it is better to create a concrete control that extends an exisiting UIComponent (like HtmlInputText does) with an equivalent renderer.
If contamination isn't an issue, there is an open-source JSF implementation in the form of Apache MyFaces.
Action listeners, such as for a CommandButton, are called during the Invoke Application phase, which is the last phase before the final Render Response phase. This is shown in The JSF Lifecycle - figure 1.
It is the only framework that I've
ever used where component creation is
a deep intricate process like this.
None of the other web frameworks
(whether in the .net world or not)
make this so painful, which is
completely inexplicable to me.
Some of the design decisions behind JSF start to make a little more sense when you consider the goals. JSF was designed to be tooled - it exposes lots of metadata for IDEs. JSF is not a web framework - it is a MVP framework that can be used as a web framework. JSF is highly extensible and configurable - you can replace 90% of the implementation on a per-application basis.
Most of this stuff just makes your job more complicated if all you want to do is slip in an extra HTML control.
The component is a composition of
several inputtext (and other) base
components, btw.
I'm assuming JSP-includes/tooling-based page fragments don't meet your requirements.
I would consider using your UIComponentELTag.createComponent to create a composite control with a UIPanel base and creating all its children from existing implementations. (I'm assuming you're using JSPs/taglibs and making a few other guesses.) You'd probably want a custom renderer if none of the existing UIPanel renderers did the job, but renderers are easy.
The best article I've found is Jsf Component Writing,
as for 2 where do I read the value for a value binding in your component you have a getter that looks like this
public String getBar() {
if (null != this.bar) {
return this.bar ;
}
ValueBinding _vb = getValueBinding("bar");
return (_vb != null) ? (bar) _vb.getValue(getFacesContext()) : null;
}
how did this get into the getValueBinding?
In your tag class setProperties method
if (bar!= null) {
if (isValueReference(bar)) {
ValueBinding vb = Util.getValueBinding(bar);
foo.setValueBinding("bar", vb);
} else {
throw new IllegalStateException("The value for 'bar' must be a ValueBinding.");
}
}