On 4/14/06, Adam Brod <[EMAIL PROTECTED]> wrote:
As an added benefit, you can get bookmarkable URLs out of the deal too.
Yep, that makes sense. Indeed, JSF today does what you want already. Here's a pattern I've used that makes life pretty easy:
<managed-bean>
<managed-bean-name>backing</managed-bean-name>
<managed-bean-class>com.foo.BackingBean</managed-bean-class>
<managed-property>
<property-name>personId</property-name>
<value>#{param.personId}</value>
</managed-property>
</managed-bean>
with a backing bean like this:
public class BackingBean implements ViewController {
private int personId;
public int getPersonId() { return this.personId; }
public void setPersonId(int personId) { this.personId = personId; }
...
public void prerender() {
// By the time you get here, personId has aready
// been converted and injected, so use it to go look
// up the relevant information
}
}
No muss ... no fuss ... if you're willing to have the exception thrown on a conversion error.
Craig
Craig-
Thanks for your response. I understand that the existing Shale remoting code wouldn't work, but as you wrote - the same principle could be applied.
"However, dealing with conversion errors on unedited request parameters (it'll likely throw an exception) is probably not as user friendly as it really ought to be. "
Back to parameter mapping: since we are talking about request URLs, we don't generally need to be concerned about user-friendly errors. A malformed URL is a developer error in this case. In most cases, we'd probably be "passing" the id from the person list to the person detail page. (To be clear, I'm talking about using action-style urls just for navigation, not for form submissions where we expect conversion errors. I find that navigating from a list page to a detail page is too heavy-weight using post-backs with potentially large datasets.)
As an added benefit, you can get bookmarkable URLs out of the deal too.
If the framework didn't do this and I were to use longs and Strings in my managed bean properties, then I'd have to write code that creates the model objects. In the exceptional case that the primitive managed properties couldn't be converted, I would probably just throw an exception. Exceptions are generally okay for developer errors that can be fixed at development time. I'd rather the framework do this basic conversion for me since it works great 90+% of the time. If I have a special case that needs special error handling, I'll hand-code those few cases (or use post-backs).
Does that make sense?
Yep, that makes sense. Indeed, JSF today does what you want already. Here's a pattern I've used that makes life pretty easy:
<managed-bean>
<managed-bean-name>backing</managed-bean-name>
<managed-bean-class>com.foo.BackingBean</managed-bean-class>
<managed-property>
<property-name>personId</property-name>
<value>#{param.personId}</value>
</managed-property>
</managed-bean>
with a backing bean like this:
public class BackingBean implements ViewController {
private int personId;
public int getPersonId() { return this.personId; }
public void setPersonId(int personId) { this.personId = personId; }
...
public void prerender() {
// By the time you get here, personId has aready
// been converted and injected, so use it to go look
// up the relevant information
}
}
No muss ... no fuss ... if you're willing to have the exception thrown on a conversion error.
Adam Brod
Product Development Team
Craig
"Craig McClanahan" <[EMAIL PROTECTED]>
Sent by: [EMAIL PROTECTED]04/14/2006 05:42 PM
Please respond to
"MyFaces Discussion" <users@myfaces.apache.org>
To"MyFaces Discussion" <users@myfaces.apache.org> cc SubjectRe: JSF can handle GET requests *just as easily* as other frameworks
On 4/14/06, Adam Brod < [EMAIL PROTECTED]> wrote:
If you wanted a GET to execute an action (and pass parameters), why not adapt Shale's url convention /[managedBeanName]/[actionMethod] (for example: /documentController/documentID?id=1234)?
This capability was specifically designed for being the back end of AJAX style requests, but it works quite nicely for bookmarkable URLs too. However ...
That would enable GET requests to go through the NavigationHandler and have even more of the JSF framework goodness.
You don't get this out of the box with the current implementation in Shale. That's because, from a JSF lifecycle point of view, Shale's phase listener fires after Restore View -- and it will do this:
* Determine that the URL matches one of the patterns it is configured
to watch for (/dynamic/* by default)
* Execute the corresponding method via a programmatic method
binding call. As a side effect, this might trigger managed bean
creation of the bean instance containing this method.
* Expect that the method has created the entire response, so it
calls FaceContext.responseComplete() and returns.
As you can see, we never actually entered Invoke Application phase, we never pay attention to anything that the invoked method returns (indeed, the expected method signature is "public void methodname()"), and we never invoke the navigation handler.
That's not saying you couldn't configure a Processor that does that sort of thing -- its just that the default one doesn't.
For a use case like a bookmarkable URL, I tend to take a different approach, because of what JSF's lifecycle will do for you anyway -- if Restore View detects that there is no view state to restore, it jumps immediately to Render Response phase. If you can interpose some processing logic that happens right before rendering, and hav that logic pull out the request parameters you need (or let JSF inject them via the managed properties stuff), then it is very straightforward to process GET requests. Shale even gives you a very easy place to put this kind of logic, if your backing bean implements ViewController -- stick it in the prerender() method. This approach certainly isn't harder than doing the same sort of thing in Struts 1.x.
Regarding conversion of request parameters to model data types, Section 5.3.1.2 of the JSF 1.1 spec discusses using managed properties to inject values into managed beans as they get created. It requires the same implicit conversions that JSP provides for the <jsp:setProperty> tag, so you're covered for things like Java primitives, but not for custom data types. That means you could use a value _expression_ like "#{ param.personId} to pull out the personId request parameter, and assign it to a bean property of type int or long. However, dealing with conversion errors on unedited request parameters (it'll likely throw an exception) is probably not as user friendly as it really ought to be. I would tend to use string properties for that reason.
Adam Brod
Product Development Team
Craig