commons-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Franklin Phan (JIRA)" <j...@apache.org>
Subject [jira] Issue Comment Edited: (BEANUTILS-353) Unable to call isUseDefault() to check whether a default value will be returned
Date Mon, 03 Aug 2009 21:28:14 GMT

    [ https://issues.apache.org/jira/browse/BEANUTILS-353?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12738264#action_12738264
] 

Franklin Phan edited comment on BEANUTILS-353 at 8/3/09 2:27 PM:
-----------------------------------------------------------------

I am trying your suggestion from your first comment, and I am seeing an inconsistency with
the workings of this "per-classloader" feature. I have two instances of Tomcat 5.5.27 running
on separate machines (one Linux and one WinXP). Each Tomcat is set up similarly and runs the
same copy of a webapp. Per your suggestion, I wrote each webapp a *Filter* whose *init* method
registers an implementation of *SqlTimestampConverter* that returns a default of null:

{code:title=EmployeeDirFilter.java|borderStyle=solid}
public class EmployeeDirFilter implements RenderFilter, ActionFilter {
    private FilterConfig config;
...
    public void init(FilterConfig filterConfig) throws PortletException {
        config = filterConfig;

        // Register a SqlTimestampConverter that returns a default of NULL
        BeanUtilsBean.getInstance().getConvertUtils().register(new SqlTimestampConverter(null),
java.sql.Timestamp.class);
    }
}
{code}

Using NetBeans Debugger, I can see that during server startup, the init method is called for
both webapps and a new instance of *BeanUtilsBeans* (containing the corrected *SqlTimestampConverter*)
is stored in the *{{valueByClassLoader}} Map* in *ContextClassLoaderLocal*. Each converter
is mapped by the *ContextClassLoader* gotten from:

{code:title=org.apache.commons.beanutils.ContextClassLoaderLocal.java get() method|borderStyle=solid}ClassLoader
contextClassLoader = Thread.currentThread().getContextClassLoader();{code}

So far so good.

Later, when the webapps are called again via a different action, one webapp retrieves the
same *BeanUtilsBeans* from the *{{valueByClassLoader}} Map* while the other webapp gets a
different *ContextClassLoader*, thereby causing a second, _new_ instance of *BeanUtilsBeans*
to be created with all the default Converters via the *{{ConvertUtilsBean.deregister}}* method
and having it stored in the *{{valueByClassLoader}} Map*. This new instance of *BeanUtilsBeans*
contains, of course, the _incorrect_ *SqlTimestampConverter*; and *{{valueByClassLoader}}
Map* now contains _two_ *BeanUtilsBeans*. What's causing this discrepant behavior in the latter
Tomcat/webapp?

In case it matters, here's the *Context* for the two webapps in each Tomcat (notice that *{{useContextClassLoader}}*
is set to *{{false}}*):
{code:title=Context element under <TOMCAT_HOME>/conf/Catalina/localhost|borderStyle=solid}
<?xml version="1.0" encoding="UTF-8"?>

<!-- For Liferay -->
<Context docBase="${catalina.base}/webapps/liferay523"
      reloadable="false" crossContext="true">
  <!-- JAAS -->

  <Realm
    className="org.apache.catalina.realm.JAASRealm"
    appName="PortalRealm"
    userClassNames="com.liferay.portal.kernel.security.jaas.PortalPrincipal"
    roleClassNames="com.liferay.portal.kernel.security.jaas.PortalRole"
    debug="99"
    useContextClassLoader="false"
  />

</Context>
{code}

      was (Author: fphan):
    I am trying your suggestion from your first comment, and I am seeing an inconsistency
with the workings of this "per-classloader" feature. I have two instances of Tomcat 5.5.27
running on separate machines (one Linux and one WinXP). Each Tomcat is set up similarly and
runs the same copy of a webapp. Per your suggestion, I wrote each webapp a *Filter* whose
*init* method registers an implementation of *SqlTimestampConverter* that returns a default
of null:

{code:title=EmployeeDirFilter.java|borderStyle=solid}
public class EmployeeDirFilter implements RenderFilter, ActionFilter {
    private FilterConfig config;
...
    public void init(FilterConfig filterConfig) throws PortletException {
        config = filterConfig;

        // Register a SqlTimestampConverter that returns a default of NULL
        BeanUtilsBean.getInstance().getConvertUtils().register(new SqlTimestampConverter(null),
java.sql.Timestamp.class);
    }
}
{code}

Using NetBeans Debugger, I can see that during server startup, the init method is called for
both webapps and a new instance of *BeanUtilsBeans* (containing the corrected *SqlTimestampConverter*)
is stored in the *{{valueByClassLoader}} Map* in *ContextClassLoaderLocal*. Each converter
is mapped by the *ContextClassLoader* gotten from:

{code:title=org.apache.commons.beanutils.ContextClassLoaderLocal.java get() method|borderStyle=solid}ClassLoader
contextClassLoader = Thread.currentThread().getContextClassLoader();{code}

So far so good.

Later, when the webapps are called again via a different action, one webapp retrieves the
same *BeanUtilsBeans* from the *{{valueByClassLoader}} Map* while the other webapp gets a
different *ContextClassLoader*, thereby causing a second, _new_ instance of *BeanUtilsBeans*
to be created with all the default Converters via the *{{ConvertUtilsBean.deregister}}* method
and having it stores in the *{{valueByClassLoader}} Map*. This new instance of *BeanUtilsBeans*
contains, of course, the _incorrect_ *SqlTimestampConverter*; and *{{valueByClassLoader}}
Map* now contains _two_ *BeanUtilsBeans*. What's causing this discrepant behavior in the latter
Tomcat/webapp?

In case it matters, here's the *Context* for the two webapps in each Tomcat (notice that *{{useContextClassLoader}}*
is set to *{{false}}*):
{code:title=Context element under <TOMCAT_HOME>/conf/Catalina/localhost|borderStyle=solid}
<?xml version="1.0" encoding="UTF-8"?>

<!-- For Liferay -->
<Context docBase="${catalina.base}/webapps/liferay523"
      reloadable="false" crossContext="true">
  <!-- JAAS -->

  <Realm
    className="org.apache.catalina.realm.JAASRealm"
    appName="PortalRealm"
    userClassNames="com.liferay.portal.kernel.security.jaas.PortalPrincipal"
    roleClassNames="com.liferay.portal.kernel.security.jaas.PortalRole"
    debug="99"
    useContextClassLoader="false"
  />

</Context>
{code}
  
> Unable to call isUseDefault() to check whether a default value will be returned
> -------------------------------------------------------------------------------
>
>                 Key: BEANUTILS-353
>                 URL: https://issues.apache.org/jira/browse/BEANUTILS-353
>             Project: Commons BeanUtils
>          Issue Type: Bug
>          Components: ConvertUtils & Converters
>    Affects Versions: 1.8.0
>         Environment: WinXP Pro, Linux, JDK 1.6.0_14, Tomcat 5.5.27
>            Reporter: Franklin Phan
>
> One can never call isUseDefault() to check on a Converter given the way you have ConverterFacade
designed and in ConvertUtilsBean:
> {code:title=org.apache.commons.beanutils.ConverUtilsBean|borderStyle=solid}
>     private void register(Class clazz, Converter converter) {
>         register(new ConverterFacade(converter), clazz);
>     }
> {code}

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


Mime
View raw message