Question

J'ai créé un Converter personnalisé dans JSF 1.2 pour convertir des objets Date. Les dates ont un format très particulier. Je l'ai mis en place mon convertisseur en utilisant la base de classe Java SimpleDateFormat pour effectuer la conversion, en utilisant la chaîne de formatter indiqué dans mes commentaires du code ci-dessous. Cela fonctionne tout va bien.

Ma question porte sur la sécurité des threads. L'API SimpleDateFormat docs indiquent qu'il est pas thread-safe. Pour cette raison, j'ai créé une instance distincte de l'objet de format de date pour chaque instance de mon objet convertisseur. Cependant, je ne sais pas si cela suffit. Mon objet DateFormat est stocké en tant que membre du DTGDateConverter.

QUESTION: Will deux fils chaque accès simultanément la même instance d'un objet Converter dans JSF

Si la réponse est oui, alors mon convertisseur est probablement à risque.

/**
 * <p>JSF Converter used to convert from java.util.Date to a string.
 * The SimpleDateFormat format used is: ddHHmm'Z'MMMyy.</p>
 * 
 * <p>Example: October 31st 2010 at 23:59 formats to 312359ZOCT10</p>
 * 
 * @author JTOUGH
 */
public class DTGDateConverter implements Converter {

    private static final Logger logger = 
        LoggerFactory.getLogger(DTGDateConverter.class);

    private static final String EMPTY_STRING = "";

    private static final DateFormat DTG_DATE_FORMAT = 
        MyFormatterUtilities.createDTGInstance();

    // The 'format' family of core Java classes are NOT thread-safe.
    // Each instance of this class needs its own DateFormat object or
    // runs the risk of two request threads accessing it at the same time.
    private final DateFormat df = (DateFormat)DTG_DATE_FORMAT.clone();

    @Override
    public Object getAsObject(
            FacesContext context, 
            UIComponent component, 
            String stringValue)
            throws ConverterException {
        Date date = null;
        // Prevent ParseException when an empty form field is submitted
        // for conversion
        if (stringValue == null || stringValue.equals(EMPTY_STRING)) {
            date = null;
        } else {
            try {
                date = df.parse(stringValue);
            } catch (ParseException e) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Unable to convert string to Date object", e);
                }
                date = null;
            }
        }
        return date;
    }

    @Override
    public String getAsString(
            FacesContext context, 
            UIComponent component, 
            Object objectValue)
            throws ConverterException {
        if (objectValue == null) {
            return null;
        } else if (!(objectValue instanceof Date)) {
            throw new IllegalArgumentException(
                "objectValue is not a Date object");
        } else {
            // Use 'toUpperCase()' to fix mixed case string returned
            // from 'MMM' portion of date format
            return df.format(objectValue).toUpperCase();
        }
    }

}
Était-ce utile?

La solution

  

deux fils chaque accès simultanément la même instance d'un objet Converter dans JSF?

Cela dépend de la façon dont vous utilisez le convertisseur. Si vous utilisez

<h:inputWhatever>
    <f:converter converterId="converterId" />
</h:inputWhatever>

alors une nouvelle instance sera créée pour chaque élément d'entrée en vue, qui est threadsafe (attendre du boîtier de bord très rare que l'utilisateur final a deux points de vue identiques dans deux onglets du navigateur dans la même session et émet simultanément une publication sur la les deux vues).

Si vous utilisez cependant

<h:inputWhatever converter="#{applicationBean.converter}" />

alors la même instance sera partagé entre tous les points de vue de l'ensemble de l'application, ce qui est donc pas threadsafe.

Vous clonage mais une instance statique DataFormat chaque fois que vous créez le convertisseur. Cette partie est déjà pas threadsafe. Vous pouvez risquer que vous dupliquez une instance alors que son état interne est été modifié, car il a été utilisé ailleurs. En outre, le clonage d'une instance existante est pas nécessairement moins cher que la création d'une nouvelle instance.

Je recommande de déclarer juste ThreadLocal (à savoir l'intérieur du bloc de méthode), quelle que soit la façon dont vous utilisez le convertisseur. Si le expensiveness de créer l'everytime DateFormat est une préoccupation majeure (avez-vous de profil lui?), Puis envisager de le remplacer par JodaTime .

Autres conseils

  

Les formats de date ne sont pas synchronisés. Il   il est recommandé de créer séparée   les instances de format pour chaque thread. Si   plusieurs threads accès format   en même temps, il doit être synchronisé   à l'extérieur.

Oui il est pas thread-safe ici.

Mettez locale à la méthode et créer par exemple fil

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top