2012-09-09 12 views
7

No estoy seguro de si se trata de un problema complejo, pero como persona inicial me parece un poco complejo. Tengo un objeto basado en el cual necesito mostrar algunos valores en la interfaz de usuario y dejar que el usuario seleccione algunos de ellos. Debo enviar datos a otro controlador cuando el usuario haga clic en el botón Enviar. Aquí está la estructura de mi objeto de datosEncuadernación de un mapa de listas en Spring MVC

public class PrsData{ 
private Map<String, List<PrsCDData>> prsCDData; 
} 

public class PrsCDData{ 
    private Map<String, Collection<ConfiguredDesignData>> configuredDesignData; 
} 

public ConfiguredDesignData{ 
    // simple fields 
} 

I han establecido el objeto en el modelo antes de que muestra la vista como

model.addAttribute("prsData", productData.getPrData()); 

en la forma que he siguiente configuración

<form:form method="post" commandName="prsData" action="${addProductToCartAction}" > 
<form:hidden path="prsCDData['${prsCDDataMap.key}'] 
    [${status.index}].configuredDesignData['${configuredDesignDataMap.key}'] 
    [${configuredDesignDataStatus.index}].code"/> 

<form:hidden path="prsCDData['${prsCDDataMap.key}'] 
    [${status.index}].configuredDesignData['${configuredDesignDataMap.key}'] 
    [${configuredDesignDataStatus.index}].description"/> 

</form:form> 

Esto es lo que tengo en AddProductToCartController

public String addToCart(@RequestParam("productCodePost") final String code, 
@ModelAttribute("prsData") final PrsData prsData, final Model model, 
@RequestParam(value = "qty", required = false, defaultValue = "1") final long qty) 

En la presentación de la forma que estoy recibiendo siguiente excepción

org.springframework.beans.NullValueInNestedPathException: Invalid property 'prsCDData[Forced][0]' 
of bean class [com.product.data.PrsData]: 
Cannot access indexed value of property referenced in indexed property path 'prsCDData[Forced][0]': returned null 

Parece que su tratando de acceder a los valores de este controlador mientras yo estoy tratando de enviar el valor a ese controlador y tratando de crear el mismo objeto con los valores seleccionados

¿Puede alguien decirme dónde estoy haciendo mal y lo que tengo que cuidar

Editar

he hecho un poco más investigación y llegaron a conocer que la primavera no son compatibles con auto-poblar la lista/mapa de objetos personalizados y en base a la respuesta que trató de cambiar la aplicación como

public class PrsData{ 
    private Map<String, List<PrsCDData>> prsCDData; 
    // lazy init 
    public PrsData() 
    { 
      this.prsCDData = MapUtils.lazyMap(new HashMap<String, List<PrsCDData>>(), 
       FactoryUtils.instantiateFactory(PrsCDData.class)); 
     } 
    } 

    public class PrsCDData{ 
     private Map<String, Collection<ConfiguredDesignData>> configuredDesignData; 
     public PrsCDData() 
    { 

     this.configuredDesignData = MapUtils.lazyMap(new HashMap<String, 
             List<ConfiguredDesignData>>(), 
      FactoryUtils.instantiateFactory(ConfiguredDesignData.class)); 

    } 
    } 

pero estoy consiguiendo siguiente excepción

org.springframework.beans.InvalidPropertyException: 
Invalid property 'prsCDData[Forced][0]' of bean class [com.data.PrsData]: 
Property referenced in indexed property path 'prsCDData[Forced][0]' 
is neither an array nor a List nor a Set nor a Map; 
returned value was [[email protected]] 

no estoy seguro de lo que lo que estoy haciendo mal, parece que sea mi expresión JSTL no está bien

+0

Otra cosa a tener en cuenta en este escenario es clases anidadas. Hacer 'PrsCDData' una clase de nivel superior podría evitar este problema. –

Respuesta

7

Explicación: si en su controlador tiene @ModelAttribute("user") User user, y carga una página correspondiente que contiene <form:form commandName="user">, se crea una instancia de un Usuario vacío.

Todos sus atributos son nulos o están vacíos en el caso de una Lista o un Mapa. Además, sus listas/mapas vacíos se han instanciado con una implementación de crecimiento automático. Qué significa eso ? Digamos que tenemos un autocrecimiento vacío List<Coconut> coconuts. Si hago coconuts.get(someIndex).setDiameter(50), funcionará en lugar de arrojar una excepción, porque la lista crece automáticamente y crea una instancia de un coco para el índice dado.
Gracias a este autogrowing, enviar un formulario con la entrada de abajo funcionarán como un encanto:

<form:input path="coconuts[${someIndex}].diameter" /> 

Ahora, de vuelta a su problema: Spring MVC autogrowing funciona bastante bien con una cadena de objetos, cada uno contiene un mapa/lista (see this post). Pero dada su excepción, parece que Spring no autogrow los posibles objetos contenidos en la lista/mapa autocreados.En Map<String, List<PrsCDData>> prsCDData, List<PrsCDData> es una mera lista vacía sin crecimiento automático, lo que lleva a su excepción.

Así que la solución debe usar algún tipo de Apache Common's LazyList o Spring's AutoPopulatingList.
Debe implementar su propio mapa de crecimiento automático que crea una LazyList/AutoPopulatingList para un índice determinado. Hágalo desde cero o utilizando algún tipo de implementación de Apache Common LazyMap/MapUtils.lazyMap (hasta ahora no he encontrado un equivalente de Spring para LazyMap).

Ejemplo de solución, utilizando Apache Commons Colecciones:

public class PrsData { 

    private Map<String, List<PrsCDData>> prsCDData; 

    public PrsData() { 
     this.prsCDData = MapUtils.lazyMap(new HashMap<String,List<Object>>(), new Factory() { 

      public Object create() { 
       return LazyList.decorate(new ArrayList<PrsCDData>(), 
          FactoryUtils.instantiateFactory(PrsCDData.class)); 
      } 

     }); 
    } 

} 
+0

¡Buena explicación! Lo intentaremos según su sugerencia y actualizaremos –

+0

probando el primer enfoque dando la siguiente excepción 'org.springframework.beans.NullValueInNestedPathException: Propiedad no válida 'prsBTOData' de la clase de bean [com.data.PrsData]: No se pudo crear una instancia del tipo de propiedad [org .springframework.util.AutoPopulatingList] para auto crecer la ruta de la propiedad anidada: java.lang.IllegalArgumentException: No se pudo crear una instancia del tipo Collection: org.springframework.util.AutoPopulatingList' –

+0

¿Puede explicar el segundo enfoque más ya que no es muy claro para yo. –

Cuestiones relacionadas