Problema:

Tenemos un Spring REST controller como este:

	@RequestMapping( 
			value = "/slots/{nodePath}/{slot}.json",  
			method = RequestMethod.DELETE,  
			produces = "application/json") 
	@ResponseBody 
	public ContentSlot deleteSlot( 
	        @RequestParam(value = "format", required = false) final String format, 
	        @RequestParam(value = "geo", required = false) final String geo, 
	        @RequestParam(value = "segment", required = false) final String segment, 
	        @RequestParam(value = "version", required = false) final String version, 
	        @PathVariable final String slot, 
	        @PathVariable final String nodePath, 
	        HttpServletRequest request, 
	        Principal principal 
	                    ) { 
                  .....
       }

Ojo en la linea que trae algo como esto:

@PathVariable final String nodePath,

Se quiere validar la cadena “nodePath”, pero no se desea tener un metodo “validador” en cada Controller que reciba esa cadena y que la valide (o transforme) en lo requerido.

Se desea que para cuando recuperemos el valor de tal objeto, este ya este validado/transformado en lo que realmente se requiere.

Para ello, hacemos lo siguiente:

1) Creamos esta anotación:

/**
 * Annotate any custom converter in the application with @UiParamConverter so it can be discovered
 * at runtime and registered
 */
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier
@Component
public @interface UiParamConverter {
}

2) Creamos esta clase convertidora:

@UiParamConverter
public class NodeConverter implements Converter {

	/**
	 * This NodePath object is used by the controllers to reference a node path in a safe way
	 */
	public static class NodePath {

		/**
		 * The nodepath (e.g. standard/home)
		 */
		private String nodePath;
		
		/**
		 * Constructor. Initializes the nodePath by converting ~ to /
		 * @param dirtyNodePath		The unvalidated node path, e.g. standard~home
		 */
		public NodePath(String dirtyNodePath) {
			if (dirtyNodePath == null) {
				throw new IllegalArgumentException("Node Path cannot be null");
			}
			if (dirtyNodePath != null) {
				nodePath = dirtyNodePath.replaceAll("[~]", "/");
			}
		}

		/**
		 * Returns the value of the node path after the validations and transformations
		 * @return		The nodepath that we want to work with
		 */
		public String get() {
			return nodePath;
		}
	}

	/**
	 * Cache for the empty node path as a performance optimization
	 */
	private static final NodePath emptyNodePath = new NodePath("");
	
	/**
	 * Implementation of the converter. Transforms a node path that is in the format of standard~home to standard/home
	 */
    @Override
    public NodePath convert(final String nodePath) {
    	if (nodePath == null) {
    		return null;
    	}
        if (ASStringUtilities.isNullOrEmpty(nodePath)) {
            return emptyNodePath;
        }
        return new NodePath(nodePath);
    }
}

3) Lo usamos en el controller original:

	public ContentSlot deleteSlot( 
	        @RequestParam(value = "format", required = false) final String format, 
	        @RequestParam(value = "geo", required = false) final String geo, 
	        @RequestParam(value = "segment", required = false) final String segment, 
	        @RequestParam(value = "version", required = false) final String version, 
	        @PathVariable final String slot, 
	        @PathVariable final NodePath nodePath, 
	        HttpServletRequest request, 
	        Principal principal 
	                    ) { 
                String value = nodePath.get();
        }

Cheers,
Goose

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)

© 2019 Goose Workshop Suffusion theme by Sayontan Sinha