You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@struts.apache.org by "Sebastian Götz (JIRA)" <ji...@apache.org> on 2012/12/03 15:03:58 UTC

[jira] [Created] (WW-3936) Custom Struts2 type converter is only called in one direction

Sebastian Götz created WW-3936:
----------------------------------

             Summary: Custom Struts2 type converter is only called in one direction
                 Key: WW-3936
                 URL: https://issues.apache.org/jira/browse/WW-3936
             Project: Struts 2
          Issue Type: Bug
          Components: Core Actions
    Affects Versions: 2.3.4.1
         Environment: JDK 1.7, Tomcat 7.0.26
            Reporter: Sebastian Götz
             Fix For: 2.3.8


We have a custom converter implemented that should convert select items from and to id. Now it seems that only when submitting the form the convertFromString method gets called. Upon rendering the page the convertToString gets never called. So while we can submit values to the model the initial selection of the select list is wrong. After some googling I found a work around by overriding the toString() method to return the id to make it work. But this is not an option in other cases where we face the same problems.
More strange is, that if I render the same into a textfield tag, the converter is triggered in both directions.

{code:title=ThemeDscriptor.java}
public class ThemeDescriptor implements Serializable, Cloneable, Comparable<ThemeDescriptor>
{
	private final String id;
	private final String displayName;
	private final File directory;
	private final String contextPath;

	public ThemeDescriptor(final String p_id, final String p_displayName, final File p_directory, final String p_contextPath)
	{
		id = p_id;
		displayName = p_displayName;
		directory = p_directory;
		contextPath = p_contextPath;
	}

	public String getId()
	{
		return id;
	}

	public String getDisplayName()
	{
		return displayName;
	}

	public File getDirectory()
	{
		return directory;
	}

	public String getContextPath()
	{
		return contextPath;
	}
}
{code}

{code:title=ThemeDescriptorConverter.java}
package eu.inform.integration.converter;

import java.util.Map;

import org.apache.log4j.LogMF;
import org.apache.log4j.Logger;

import com.opensymphony.xwork2.conversion.TypeConversionException;

import eu.inform.presentation.ThemeDescriptor;
import eu.inform.presentation.UIConstants;

public class ThemeDescriptorConverter extends AbstractBaseConverter
{
	private final static Logger log = Logger.getLogger(ThemeDescriptorConverter.class);

	@SuppressWarnings("rawtypes")
	@Override
	public Object convertFromString(final Map p_context, final String[] p_values, final Class p_toClass)
	{
		if ((p_values != null) && (p_values.length > 0))
		{
			try
			{
				Map<String, ThemeDescriptor> themes = UIConstants.getThemes();
				if (themes.containsKey(p_values[0]))
				{
					return themes.get(p_values[0]);
				}

				throw new RuntimeException("No theme with id: " + p_values[0]);
			}
			catch (Exception e)
			{
				LogMF.error(log, e, "Unable to convert {0} into a ThemeDescriptor", new Object[] { p_values[0] });

				throw new TypeConversionException("Unable to convert into a ThemeDescriptor: " + p_values[0], e);
			}
		}
		return null;
	}

	@SuppressWarnings("rawtypes")
	@Override
	public String convertToString(final Map p_context, final Object p_o)
	{
		try
		{
			return ((ThemeDescriptor) p_o).getId();
		}
		catch (Exception e)
		{
			LogMF.error(log, e, "Unable to convert {0} into a string", new Object[] { p_o });
		}

		return null;
	}
}
{code}

{code:xml|title=JSP}
<s:form method="POST" action="design" theme="simple">
<div  style="width:95%;">
	<table>
		<tr>
			<td><s:text name="choose" /></td>
			<td><s:select key="design" id="design" list="designList" listValue="value.displayName" /></td>
			<td><s:submit key="save" /></td>
		</tr>
	</table>
	</div>
</s:form>
{code}

{code:xml|title=xwork-conversion.properties}
eu.inform.presentation.ThemeDescriptor=eu.inform.integration.converter.ThemeDescriptorConverter
{code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Updated] (WW-3936) Custom Struts2 type converter is only called in one direction

Posted by "Sebastian Götz (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/WW-3936?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Sebastian Götz updated WW-3936:
-------------------------------

    Fix Version/s:     (was: 2.3.8)
                   2.3.x
    
> Custom Struts2 type converter is only called in one direction
> -------------------------------------------------------------
>
>                 Key: WW-3936
>                 URL: https://issues.apache.org/jira/browse/WW-3936
>             Project: Struts 2
>          Issue Type: Bug
>          Components: Core Actions
>    Affects Versions: 2.3.4.1
>         Environment: JDK 1.7, Tomcat 7.0.26
>            Reporter: Sebastian Götz
>             Fix For: 2.3.x
>
>
> We have a custom converter implemented that should convert select items from and to id. Now it seems that only when submitting the form the convertFromString method gets called. Upon rendering the page the convertToString gets never called. So while we can submit values to the model the initial selection of the select list is wrong. After some googling I found a work around by overriding the toString() method to return the id to make it work. But this is not an option in other cases where we face the same problems.
> More strange is, that if I render the same into a textfield tag, the converter is triggered in both directions.
> {code:title=ThemeDscriptor.java}
> public class ThemeDescriptor implements Serializable, Cloneable, Comparable<ThemeDescriptor>
> {
> 	private final String id;
> 	private final String displayName;
> 	private final File directory;
> 	private final String contextPath;
> 	public ThemeDescriptor(final String p_id, final String p_displayName, final File p_directory, final String p_contextPath)
> 	{
> 		id = p_id;
> 		displayName = p_displayName;
> 		directory = p_directory;
> 		contextPath = p_contextPath;
> 	}
> 	public String getId()
> 	{
> 		return id;
> 	}
> 	public String getDisplayName()
> 	{
> 		return displayName;
> 	}
> 	public File getDirectory()
> 	{
> 		return directory;
> 	}
> 	public String getContextPath()
> 	{
> 		return contextPath;
> 	}
> }
> {code}
> {code:title=ThemeDescriptorConverter.java}
> package eu.inform.integration.converter;
> import java.util.Map;
> import org.apache.log4j.LogMF;
> import org.apache.log4j.Logger;
> import com.opensymphony.xwork2.conversion.TypeConversionException;
> import eu.inform.presentation.ThemeDescriptor;
> import eu.inform.presentation.UIConstants;
> public class ThemeDescriptorConverter extends AbstractBaseConverter
> {
> 	private final static Logger log = Logger.getLogger(ThemeDescriptorConverter.class);
> 	@SuppressWarnings("rawtypes")
> 	@Override
> 	public Object convertFromString(final Map p_context, final String[] p_values, final Class p_toClass)
> 	{
> 		if ((p_values != null) && (p_values.length > 0))
> 		{
> 			try
> 			{
> 				Map<String, ThemeDescriptor> themes = UIConstants.getThemes();
> 				if (themes.containsKey(p_values[0]))
> 				{
> 					return themes.get(p_values[0]);
> 				}
> 				throw new RuntimeException("No theme with id: " + p_values[0]);
> 			}
> 			catch (Exception e)
> 			{
> 				LogMF.error(log, e, "Unable to convert {0} into a ThemeDescriptor", new Object[] { p_values[0] });
> 				throw new TypeConversionException("Unable to convert into a ThemeDescriptor: " + p_values[0], e);
> 			}
> 		}
> 		return null;
> 	}
> 	@SuppressWarnings("rawtypes")
> 	@Override
> 	public String convertToString(final Map p_context, final Object p_o)
> 	{
> 		try
> 		{
> 			return ((ThemeDescriptor) p_o).getId();
> 		}
> 		catch (Exception e)
> 		{
> 			LogMF.error(log, e, "Unable to convert {0} into a string", new Object[] { p_o });
> 		}
> 		return null;
> 	}
> }
> {code}
> {code:xml|title=JSP}
> <s:form method="POST" action="design" theme="simple">
> <div  style="width:95%;">
> 	<table>
> 		<tr>
> 			<td><s:text name="choose" /></td>
> 			<td><s:select key="design" id="design" list="designList" listValue="value.displayName" /></td>
> 			<td><s:submit key="save" /></td>
> 		</tr>
> 	</table>
> 	</div>
> </s:form>
> {code}
> {code:xml|title=xwork-conversion.properties}
> eu.inform.presentation.ThemeDescriptor=eu.inform.integration.converter.ThemeDescriptorConverter
> {code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Commented] (WW-3936) Custom Struts2 type converter is only called in one direction

Posted by "Lukasz Lenart (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/WW-3936?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13509011#comment-13509011 ] 

Lukasz Lenart commented on WW-3936:
-----------------------------------

Did you try to use @Element annotation [1] or configure type conversion for Collections [2]?

[1] http://struts.apache.org/2.x/docs/element-annotation.html
[2] http://struts.apache.org/2.x/docs/type-conversion.html#TypeConversion-CollectionandMapSupport
                
> Custom Struts2 type converter is only called in one direction
> -------------------------------------------------------------
>
>                 Key: WW-3936
>                 URL: https://issues.apache.org/jira/browse/WW-3936
>             Project: Struts 2
>          Issue Type: Bug
>          Components: Core Actions
>    Affects Versions: 2.3.4.1
>         Environment: JDK 1.7, Tomcat 7.0.26
>            Reporter: Sebastian Götz
>             Fix For: 2.3.x
>
>
> We have a custom converter implemented that should convert select items from and to id. Now it seems that only when submitting the form the convertFromString method gets called. Upon rendering the page the convertToString gets never called. So while we can submit values to the model the initial selection of the select list is wrong. After some googling I found a work around by overriding the toString() method to return the id to make it work. But this is not an option in other cases where we face the same problems.
> More strange is, that if I render the same into a textfield tag, the converter is triggered in both directions.
> {code:title=ThemeDscriptor.java}
> public class ThemeDescriptor implements Serializable, Cloneable, Comparable<ThemeDescriptor>
> {
> 	private final String id;
> 	private final String displayName;
> 	private final File directory;
> 	private final String contextPath;
> 	public ThemeDescriptor(final String p_id, final String p_displayName, final File p_directory, final String p_contextPath)
> 	{
> 		id = p_id;
> 		displayName = p_displayName;
> 		directory = p_directory;
> 		contextPath = p_contextPath;
> 	}
> 	public String getId()
> 	{
> 		return id;
> 	}
> 	public String getDisplayName()
> 	{
> 		return displayName;
> 	}
> 	public File getDirectory()
> 	{
> 		return directory;
> 	}
> 	public String getContextPath()
> 	{
> 		return contextPath;
> 	}
> }
> {code}
> {code:title=ThemeDescriptorConverter.java}
> package eu.inform.integration.converter;
> import java.util.Map;
> import org.apache.log4j.LogMF;
> import org.apache.log4j.Logger;
> import com.opensymphony.xwork2.conversion.TypeConversionException;
> import eu.inform.presentation.ThemeDescriptor;
> import eu.inform.presentation.UIConstants;
> public class ThemeDescriptorConverter extends AbstractBaseConverter
> {
> 	private final static Logger log = Logger.getLogger(ThemeDescriptorConverter.class);
> 	@SuppressWarnings("rawtypes")
> 	@Override
> 	public Object convertFromString(final Map p_context, final String[] p_values, final Class p_toClass)
> 	{
> 		if ((p_values != null) && (p_values.length > 0))
> 		{
> 			try
> 			{
> 				Map<String, ThemeDescriptor> themes = UIConstants.getThemes();
> 				if (themes.containsKey(p_values[0]))
> 				{
> 					return themes.get(p_values[0]);
> 				}
> 				throw new RuntimeException("No theme with id: " + p_values[0]);
> 			}
> 			catch (Exception e)
> 			{
> 				LogMF.error(log, e, "Unable to convert {0} into a ThemeDescriptor", new Object[] { p_values[0] });
> 				throw new TypeConversionException("Unable to convert into a ThemeDescriptor: " + p_values[0], e);
> 			}
> 		}
> 		return null;
> 	}
> 	@SuppressWarnings("rawtypes")
> 	@Override
> 	public String convertToString(final Map p_context, final Object p_o)
> 	{
> 		try
> 		{
> 			return ((ThemeDescriptor) p_o).getId();
> 		}
> 		catch (Exception e)
> 		{
> 			LogMF.error(log, e, "Unable to convert {0} into a string", new Object[] { p_o });
> 		}
> 		return null;
> 	}
> }
> {code}
> {code:xml|title=JSP}
> <s:form method="POST" action="design" theme="simple">
> <div  style="width:95%;">
> 	<table>
> 		<tr>
> 			<td><s:text name="choose" /></td>
> 			<td><s:select key="design" id="design" list="designList" listValue="value.displayName" /></td>
> 			<td><s:submit key="save" /></td>
> 		</tr>
> 	</table>
> 	</div>
> </s:form>
> {code}
> {code:xml|title=xwork-conversion.properties}
> eu.inform.presentation.ThemeDescriptor=eu.inform.integration.converter.ThemeDescriptorConverter
> {code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Commented] (WW-3936) Custom Struts2 type converter is only called in one direction

Posted by "Sebastian Götz (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/WW-3936?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13509547#comment-13509547 ] 

Sebastian Götz commented on WW-3936:
------------------------------------

Hi Lukasz,

yes I tried the collecton conversion type configuration with the following settings:

{code:title=DesignAction-conversion.properties}
Element_designList=eu.inform.presentation.ThemeDescriptor
{code}

while this is my action class:
{code:title=DesignAction.java}

public class DesignAction extends BaseAction<BaseModel>
{
	private static final long serialVersionUID = 1L;

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

	private static final List<String> appropriateActions = new ArrayList<String>();

	public Map<String, ThemeDescriptor> getDesignList()
	{
		return UIConstants.getThemes();
	}

	@Override
	public BaseModel getModel()
	{
		return getBaseModel();
	}

	@Action(value = DESIGN_EXECUTE, results = @Result(type = "tiles", location = "design"))
	@Override
	public String execute() throws Exception
	{
		LogMF.entering(logger, "DesignAction", "execute");
		saveBreadcrumb(DESIGN_EXECUTE, getHref(), "", appropriateActions);
		return finish();
	}
}
{code}

We cannot use element annotation since we do not want intrusive ui configuration in the data layer where our actual domain objects reside. The two are strictly divided.
                
> Custom Struts2 type converter is only called in one direction
> -------------------------------------------------------------
>
>                 Key: WW-3936
>                 URL: https://issues.apache.org/jira/browse/WW-3936
>             Project: Struts 2
>          Issue Type: Bug
>          Components: Core Actions
>    Affects Versions: 2.3.4.1
>         Environment: JDK 1.7, Tomcat 7.0.26
>            Reporter: Sebastian Götz
>             Fix For: 2.3.x
>
>
> We have a custom converter implemented that should convert select items from and to id. Now it seems that only when submitting the form the convertFromString method gets called. Upon rendering the page the convertToString gets never called. So while we can submit values to the model the initial selection of the select list is wrong. After some googling I found a work around by overriding the toString() method to return the id to make it work. But this is not an option in other cases where we face the same problems.
> More strange is, that if I render the same into a textfield tag, the converter is triggered in both directions.
> {code:title=ThemeDscriptor.java}
> public class ThemeDescriptor implements Serializable, Cloneable, Comparable<ThemeDescriptor>
> {
> 	private final String id;
> 	private final String displayName;
> 	private final File directory;
> 	private final String contextPath;
> 	public ThemeDescriptor(final String p_id, final String p_displayName, final File p_directory, final String p_contextPath)
> 	{
> 		id = p_id;
> 		displayName = p_displayName;
> 		directory = p_directory;
> 		contextPath = p_contextPath;
> 	}
> 	public String getId()
> 	{
> 		return id;
> 	}
> 	public String getDisplayName()
> 	{
> 		return displayName;
> 	}
> 	public File getDirectory()
> 	{
> 		return directory;
> 	}
> 	public String getContextPath()
> 	{
> 		return contextPath;
> 	}
> }
> {code}
> {code:title=ThemeDescriptorConverter.java}
> package eu.inform.integration.converter;
> import java.util.Map;
> import org.apache.log4j.LogMF;
> import org.apache.log4j.Logger;
> import com.opensymphony.xwork2.conversion.TypeConversionException;
> import eu.inform.presentation.ThemeDescriptor;
> import eu.inform.presentation.UIConstants;
> public class ThemeDescriptorConverter extends AbstractBaseConverter
> {
> 	private final static Logger log = Logger.getLogger(ThemeDescriptorConverter.class);
> 	@SuppressWarnings("rawtypes")
> 	@Override
> 	public Object convertFromString(final Map p_context, final String[] p_values, final Class p_toClass)
> 	{
> 		if ((p_values != null) && (p_values.length > 0))
> 		{
> 			try
> 			{
> 				Map<String, ThemeDescriptor> themes = UIConstants.getThemes();
> 				if (themes.containsKey(p_values[0]))
> 				{
> 					return themes.get(p_values[0]);
> 				}
> 				throw new RuntimeException("No theme with id: " + p_values[0]);
> 			}
> 			catch (Exception e)
> 			{
> 				LogMF.error(log, e, "Unable to convert {0} into a ThemeDescriptor", new Object[] { p_values[0] });
> 				throw new TypeConversionException("Unable to convert into a ThemeDescriptor: " + p_values[0], e);
> 			}
> 		}
> 		return null;
> 	}
> 	@SuppressWarnings("rawtypes")
> 	@Override
> 	public String convertToString(final Map p_context, final Object p_o)
> 	{
> 		try
> 		{
> 			return ((ThemeDescriptor) p_o).getId();
> 		}
> 		catch (Exception e)
> 		{
> 			LogMF.error(log, e, "Unable to convert {0} into a string", new Object[] { p_o });
> 		}
> 		return null;
> 	}
> }
> {code}
> {code:xml|title=JSP}
> <s:form method="POST" action="design" theme="simple">
> <div  style="width:95%;">
> 	<table>
> 		<tr>
> 			<td><s:text name="choose" /></td>
> 			<td><s:select key="design" id="design" list="designList" listValue="value.displayName" /></td>
> 			<td><s:submit key="save" /></td>
> 		</tr>
> 	</table>
> 	</div>
> </s:form>
> {code}
> {code:xml|title=xwork-conversion.properties}
> eu.inform.presentation.ThemeDescriptor=eu.inform.integration.converter.ThemeDescriptorConverter
> {code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira