3

I have a few managed bean (ViewScoped) that are currently initialized with data in the session. I would like to initialize them with a URL GET parameter so I can provide URLs with the entity ID I want to display in my view. Something like displayClient.xhtml?entityId=123.

Right now I am thinking of something like this in the getter of the view main entity :

public clientModel getclientM() {
  if (this.clientM == null) {
    // TODO: Check for empty, non-integer or garbage parameters...
    // Anything exists to "sanitize" URL parameters?
    int entityId = Integer.parseInt(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("entityId"));

    // I guess I should check here if the logged user is authorized to 
    // load client entity with this entityId...  anything else to check?

    this.clientM = this.clientS.find(entityId);
  }

  return this.clientM;
}

Any hint or suggestion of best practices would be greatly appreciated.

ForguesR
  • 3,558
  • 1
  • 17
  • 39
  • But why? Beans are managed in http session, not in URLs – MGorgon Jul 14 '14 at 19:57
  • Are you talking about viewparams? http://stackoverflow.com/questions/6377798/what-can-fmetadata-and-fviewparam-be-used-for – Jaqen H'ghar Jul 14 '14 at 20:33
  • @Jaqen H´ghar Looks like you found exctaly what I want. I didn't know JSF was supporting parameters like this. Do I need to further _sanitize_ the f:viewparams or it can be trusted this way? – ForguesR Jul 14 '14 at 23:10
  • I'd say unless they are binded to a String they have been through a converter and are therefore totally safe. And you also have the option to use a validator. If binded to a String you should probably consider what exactly it will be used for. You can even bind it directly to bean.clientM and use a converter - this converter should then convert the String to Integer and find() the entity, so it will throw a NumberFormatException if parameter is not valid – Jaqen H'ghar Jul 15 '14 at 09:03

3 Answers3

2

I'd think something along these lines are best practice:

displayclient.xhtml:

<f:metadata>
    <f:viewParam name=“entityId” 
                 value="#{bean.clientM}” 
                 required="true" 
                 converter=“clientModelConverter”
                 converterMessage="Bad request. Unknown ClientModel.”
                 requiredMessage="Bad request. Please use a link from within the system.">
    </f:viewParam>
</f:metadata>

Converter:

@ManagedBean    
@RequestScoped 
public class ClientModelConverter implements Converter {

    @EJB
    private ClientService clientService;

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        // TODO: check if value is instanceof ClientModel
        return String.valueOf(((ClientModel) value).getId());
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
       // TODO: catch NumberFormatException and throw ConverterException
       return clientService.find(Integer.valueOf(value));
    }

}

Call the page with for example:

<h:link value=“Display” outcome="displayClient">
    <f:param name=“entityId" value=“#{…}” />
</h:link>

or just a raw url for example displayClient.xhtml?entityId=123.

Heavily inspired by What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for? and JSF 2.0 view parameters to pass objects.

Community
  • 1
  • 1
Jaqen H'ghar
  • 4,305
  • 2
  • 14
  • 26
0
  1. Store entityId in session, for example SessionScoped Bean
  2. In your View Scoped managed beans, add @PostConstruct method, where you will get entityId from session and populate data with this
MGorgon
  • 2,547
  • 23
  • 41
  • This is exactly what I have now. Why I want to use URL get parameters is because my Web App will be _linked_ with an other app. – ForguesR Jul 14 '14 at 20:04
0

I did something similar, for the same exact reason : Providing an external link to a jsf page.

In your ViewScoped bean, have a @PostConstruct method to force a fail-safe scan for the Get Param

@PostConstruct
public void scanEntityId(){

    int entityId = 0; // or some other default value 

    try{
        // Try to fetch entityId from url with GET
        int entityId = Integer.getInteger(FacesContext.getExternalContext().getRequestParameterMap().get("entityId")  );
    }catch(Exception e){
        // Did not find anything from GET
    }

    // TODO: do stuff using the entityId's value. e.g.:
    if(entityId >0){
        this.clientM = this.clientS.find(entityId);
    }
}

Just make sure to handle the cases where the entityId var is not found in the Get params

If you want to link to that page from another xhtml page of the same app, you can use the f:param

<h:link value="Go in a page that uses thatViewScoped Bean"
    outcome="#{thatViewScopedBean.takeMeToThatPage}" >      
    <f:param name="entityId" value="#{somebean.somevar.entityId}" />
</h:link>

A nice tutorial can also be found here You might also like to see this answer, and this article to see more options and get a more clear view.

Community
  • 1
  • 1
yannicuLar
  • 3,083
  • 3
  • 32
  • 50
  • Is there a reason for this instead of f:viewparam? – Jaqen H'ghar Jul 15 '14 at 08:53
  • http://stackoverflow.com/a/19453282/879368 – yannicuLar Jul 15 '14 at 09:46
  • @JaqenH'ghar You proposed a h:link with f:param too. I'm not sure I get what you mean. – yannicuLar Jul 15 '14 at 09:50
  • 1
    But you are not using the ViewParam, which for me looks as the standard route to go. Yes result is more or less the same, only you have the code in postconstruct where I have it in a converter. Anyway, everything probably works we just have too many options :-) – Jaqen H'ghar Jul 15 '14 at 09:57
  • 1
    I'm using the link/f:param to link to the page, like you did. It has nothing to do with 'reading' the identityId param. The viewParam with the Converter (looks neat btw, I didn't think about it :) ) is used to *read* the value, while f:param is used to *set* it. – yannicuLar Jul 15 '14 at 10:13
  • I read the question the other way around, that it primarily is about reading the parameter – Jaqen H'ghar Jul 15 '14 at 10:16
  • Oh, I thought you were comparing f:param with f:viewParam. my bad, Sorry !. Well, I guess the converter idea is a more dalicate way to read the value, after all, @BallusC proposed it !! I'll upvote your answer – yannicuLar Jul 15 '14 at 10:32
  • Sorry if I were not specific, but no worries :-) – Jaqen H'ghar Jul 15 '14 at 10:33