2

I'm currently reviewing code and found CDI converters like:

@Named
@RequestScoped
public class BankConverter implements Converter, Serializable
{
    @EJB
    private BankService bankService;

    @Override
    public Object getAsObject( FacesContext ctx, UIComponent comp, String identifier )
    {
        if ( identifier == null || identifier.trim().isEmpty() )
        {
            return null;
        }

        Bank bank = null;

        try
        {       
            bank = this.bankService.findByPrimaryKey( Long.valueOf( identifier ) );
        }
        catch( Exception e )
        {
            // omitted
        }

        return bank;
    }

    @Override
    public String getAsString( FacesContext ctx, UIComponent comp, Object obj )
    {
        if ( obj == null || ( ( Bank ) obj ).getId() == null )
        {
            return null;
        }

        return ( ( Bank ) obj ).getId().toString();
    }

}

The converters are basically always used like this (note the converter="#{bankConverter}"):

<p:autoComplete id="bank"
                value="#{employeeDepotManager.selectedBank}"
                var="bnk"
                converter="#{bankConverter}"
                completeMethod="#{autoCompleter.completeBankSearch}"
                itemLabel="#{bnk.name}"
                itemValue="#{bnk}"
                forceSelection="false"
                minQueryLength="3"
                global="true"
                validator="#{employeeDepotManager.validateBank}"
                scrollHeight="200">
    <p:ajax event="itemSelect" update="bank-code bank-name" />
    <p:column>#{bnk.code}</p:column>
    <p:column>#{bnk.name}</p:column>
</p:autoComplete>                    

I am currently discussing with a colleague about which scope would be the best for the converters...

95% of the manager beans referenced from the JSF pages are @ViewScoped and so I thought it would be best for the converters to be @ViewScoped as well (instead of @RequestScoped, which as far as I understand would recreate a converter instance per AJAX request).

Then my colleague added, that the converter should probably be @Dependent as this would automatically put the converters into the scope the the surrounding beans are in. My feeling said, this wouldn't work. However, I couldn't really disagree as my knowledge pretty much ends here.

So, what would probably be the best scope for converters when almost all beans referenced from JSF are @ViewScoped?

PS: Note that we are using Seam 3 to mix @Named and @ViewScoped

Kawu
  • 13,647
  • 34
  • 123
  • 195

1 Answers1

3

As most part of the converters are actually stateless, they could easily be @ApplicationScoped, which is, in my opinion, the most natural scope for them. Nonetheless, some converters actually aren't. For example, DateTimeConverter behind <f:convertDateTime> tag does hold some state. Moreover, the default implementation of @FacesConverter uses Application#createConverter(String converterId) that creates a new converter instance when it is needed, so it can be created more than once per request.

Also, as far as I'm concerned custom converters don't have any intersection with the referenced backing beans in terms of scope, so it doesn't matter whether they are ViewScoped or not. What actually matters when choosing scope of a converter is the scope of the state held in the converter instance, as it was rightly spotted by BalusC.

As far as the converter in your question in fact is stateless, it can safely be @ApplicationScoped.

skuntsel
  • 11,624
  • 11
  • 44
  • 67
  • 3
    Note that not *all* converters are stateless. E.g. [`DateTimeConverter`](http://grepcode.com/file/repo1.maven.org/maven2/javax.faces/jsf-api/2.1/javax/faces/convert/DateTimeConverter.java#184) behind `` isn't. The particular one in the question however is, so it can indeed safely be `@ApplicationScoped`. So, the answer ultimately boils down to: depends on the scope of the state as hold in the converter instance. – BalusC Apr 11 '13 at 19:00
  • 1
    @BalusC: I had to search a little to find the example I copied this from (you). It is at http://balusc.blogspot.de/2011/09/communication-in-jsf-20.html#ProcessingGETRequestParameters . Why did you use `@ViewScoped` here? @All: For my concrete example (and the above), so it would probably most practical to omit the scope annotation as long as you reference stateless beans via `@EJB` or `@Inject`? As soon as bean of other scopes are used, the scope **should** probably be the same? I'm looking for a **best practice** actually... – Kawu Apr 12 '13 at 07:40
  • BalusC did use `@ViewScoped` annotation **for the managed bean** and `@RequestScoped` annotation **for converter**. The request scope used in converter means that it will be created on a per-request basis, whereas if it were put in application scope it would be created once and used to convert every object, if necessary. The last approach, however, can be implemented if your converter *is stateless*. Omitting scope is actually a bad idea, unless you know what you're doing, because you'll be otherwise left with a [default scope](http://docs.jboss.org/seam/snapshot/en-US/html/concepts.html). – skuntsel Apr 12 '13 at 08:24
  • @BalusC Thank you for a clever correction. `DateTimeConverter` is indeed not stateless, so my answer is in fact not logically correct. Don't you mind that I included your investigations in the answer? – skuntsel Apr 12 '13 at 08:31
  • 1
    Skuntsel, feel free to fix your answer. Kawu, as to my blog, that was just to be on the safe side, you never know with copypasting starters. E.g. UserService might in their case be stateful. I've at least updated [the blog example](http://balusc.blogspot.de/2011/09/communication-in-jsf-20.html#ConvertingAndValidatingGETRequestParameters) with a comment behind @RequestScoped. – BalusC Apr 12 '13 at 10:52
  • Great discussion going on here. I don't want to throw a monkey wrench in things, but we're no longer actively developing Seam 3, and unfortunately Apache DeltaSpike isn't quite ready yet, it's still production worthy, just doesn't have all the JSF stuff in there yet. Feel free to continue using Seam 3, but you'll have to self support. – LightGuard Apr 13 '13 at 17:13
  • @BalusC at the risk of sounding stupid I think there is an error on your blog on the page mentioned above. in " Converting and validating GET request parameters" in the fonction you are using modelValue then value which is defined nowhere. if (modelValue instanceof User) { return String.valueOf(((User) value).getId()); } – Ced Oct 23 '15 at 15:25
  • @Ced: typo has been fixed. Thank you. – BalusC Oct 23 '15 at 15:27