Mostrando entradas con la etiqueta struts. Mostrar todas las entradas
Mostrando entradas con la etiqueta struts. Mostrar todas las entradas

lunes, 25 de febrero de 2013

Hacer un redirect con struts

Problema: He creado un post, y el forward me llevó al listado de post, sin embargo, como la url es /crearActionPost.do  , si le doy a refrescar me volverá a crear el mismo post.  Quiero que me cambie la url, para que aunque refresquen, sea imposible volver a crear el mismo post, que para crear un post, deban iniciar el proceso.

Solución:

   Esto sería lo que tendría habitualmente:  //return mapping.findForward("mostrarTodo");
 Esta, una primera aproximación: 
    // ActionForward ac = mapping.findForward("mostrarTodo");
    // ac.setRedirect(true);
    //return ac;
   En realidad ActionForward, hereda de ForwardConfig, entonces, puedo decirle, que quiero que 
vaya al listado pero indicándole que haga un redirect:       
    ForwardConfig f = new ActionRedirect(mapping.findForward("mostrarTodo"));
    f.setRedirect(true);
    return (ActionForward) f;

html:href .vs. a href

Problema:  Queremos llamar desde una jsp a un action de struts.
Posibilidades:  Usar una etiqueta "a" de html o usar una etiqueta "Conclusión:  Mejor usar la de Struts, puesto que relativiza y puedes llamar a un action sin .do y sin tener en cuenta dónde desde dónde haces la llamada.  Peor si quieres imprimir varios parámetros o usar el <bean:write>


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"

    pageEncoding="ISO-8859-1"%>

    <%@page import="vo.PostVO" %>

    <%@page import="java.util.LinkedList" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>

<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>

<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<title></title>

</head>

<body>

<logic:iterate name="listaPost"  scope="session" id="post" >

    <bean:write property="titulo" name="post"/>

    <bean:write property="descripcion" name="post"/>

    <bean:write property="fecha" name="post"/>

    <a href="postAction.do?method=detallesPost&id=<bean:write property="id" name="post"/>">Más detalles...</a></br></br>

</logic:iterate> 
 
 
<!--


OPCIÓN 1:

con a href, debo buscar la ruta relativa y colocar el .do 

--> 
 <a href="../crearPost.do">Crear nuevo Post</a>
 
 
<!--

OPCIÓN 2:con html:link, no es necesario colocar .do ni las relativas

-->  


 <html:link action="crearPost">Crear nuevo Post versión pro</html:link> 
 
<!--


OPCIÓN 3:con html:link, pasándole un parámetro ID, donde adquiere el valor que tendrá la propiedad id dentro del form llamado post

http://localhost:8080/nombre_proyecto/crearPost.do?method=crear&titulo=4&ID=2

--> 

 
 <html:link action='crearPost?method=crear&titulo=4' paramName="post" 
paramProperty="id" paramId="ID" >Crear nuevo Post versión pro</html:link>



</body>

</html>






lunes, 21 de enero de 2013

Hibernate desde 0 usando Struts 1.3.10

Hoy me topé con la necesidad de integrar Hibernate junto con Struts, y aquí os dejo unos pasos y unos buenos tutoriales

1.-Me bajé el zip con el contenido de hibernate.  https://sourceforge.net/projects/hibernate/?source=dlp  y en el eclipse, en la carpeta lib, metí los jars siguientes:
  • Los que estaban dentro de required ( hibernate-distribution-3.6.10.Final-dist\hibernate-distribution-3.6.10.Final\lib\required) : antlr-2.7.6, commons-collections-3.1, dom4j-1.6.1, javassist-3.12.0.GA, jta-1.1,  slf4j-api-1.6.1
  • Los de hibernate propiamente dicho (\hibernate-distribution-3.6.10.Final-dist\hibernate-distribution-3.6.10.Final) : hibernate3  e hibernate3testing 
  • El de JPA (hibernate-distribution-3.6.10.Final-dist\hibernate-distribution-3.6.10.Final\lib\jpa):  hibernate-jpa-2.0-api-1.0.1.Final
    • Este jar hay que meterlo para evitar la excepción Exception in thread “main” java.lang.NoClassDefFoundError: javax/persistence/EntityListeners    (solución hallada en http://technicalrecyclebin.wordpress.com/category/j2ee/hibernate/ )
2.-Metí en mi proyecto el jar de un conector de mysql, en mi caso:  mysql-connector-java-5.1.22-bin.jar

3.-Yo seguí un muy buen tutorial de creación de la aplicación, donde tras indicarte los ficheros que tienes que crear te brinda la oportunidad de dejar la prueba ejecutada
http://blog.sencide.com/2011/03/hibernate-tutorial-for-beginners.html

4.-Para ese mismo tutorial, os dejo los scripts de creación de mysql, puesto que , tuve algún error, por ejemplo, se me olvidó crear las claves primaras como autoincremental, y si no lo hacía, me salía el siguiente error:   org.hibernate.HibernateException: The database returned no natively generated identity value  o también otro que indicaba que no tenía un valor por defecto en el id.  OJO, yo le llamé a la base de datos, hibernatestruts  (con lo cual difiere del ejemplo del tutorial)

delimiter $$

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(100) DEFAULT NULL,
  `last_name` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8$$

delimiter $$

CREATE TABLE `tasks` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `title` varchar(100) DEFAULT NULL,
  `description` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8$$

SELECT * FROM hibernatestruts.users;

delimiter $$

CREATE TABLE `tasks` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `title` varchar(100) DEFAULT NULL,
  `description` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8$$

SELECT * FROM hibernatestruts.users;

5.-Una vez que ejecuté como una aplicación Java el test.  Procedí a introducirlo con Struts.  Para ello, tenía una aplicación creada con el struts-blank de la versión 1.3.10, creé un Action para poder ejecutar mi código y seguí el siguiente tutorial:

http://bernabetorres.wordpress.com/2011/07/27/integracion-de-hibernate-en-struts-1-3-10/

y este

http://www.mkyong.com/struts/struts-hibernate-integration-example/


6.-Finalmente, me leí una documentación adicional

Introducción resumida:  http://hareenlaks.blogspot.com.es/2011/03/introduction-to-hibernate.html
Introducción: http://docs.jboss.org/hibernate/core/3.5/reference/en/html/tutorial.html
Lenguaje HQL:  http://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html
Variado: http://viralpatel.net/blogs/introduction-to-hibernate-framework-architecture/

7.-No olvidar, una buena herramienta para el eclipse (en mi caso eclipse Juno)
http://marketplace.eclipse.org/node/420896#.UP0aLoaTrIU

martes, 28 de agosto de 2007

Validación usando validation.xml, validator-rules.xml y un validador propio

Problema: Hacer un validador externo para ser usado desde el validation.xml.

Solución:
1.- Hago una clase que tenga mi método de validación

public class MiValidation implements Serializable{

/**
* Valida un dce con el formato de dos dígitos seguidos de una barra y luego 4 dígitos. Ej.: 33/12345
* @return false si no hubo error, true si hubo algún error
*/
public static boolean validateDCE(java.lang.Object bean,
org.apache.commons.validator.ValidatorAction va,
org.apache.commons.validator.Field field, ActionMessages errors,
Validator validator, javax.servlet.http.HttpServletRequest request) {
// reflejamos el metodo en el logger
if (ValidationCortas.logger.isDebugEnabled()) {
ValidationCortas.logger
.debug("ValidationCortas: Método validateDCE");
}

// miramos si el objeto es un string
String value = null;
if (MiValidation.isString(bean)) {
// metemos el string en la variable value
value = ((String) bean);
} else {
// obetenemos el valor del bean
value = ValidatorUtils.getValueAsString(bean, field.getProperty());
}

// comprobamos que tenga algo
if (!GenericValidator.isBlankOrNull(value)) { //esa función es propia es para que no sea null o cadena vacía
String expReg = "^(\\d{2})(/\\d{4})$"; //ej.: 33/12345
boolean mach=value.matches(expReg);
if (value.matches(expReg) ){
return (false);
}else{
errors.add(field.getKey(), Resources.getActionMessage(request, va,
field));
return (true);

}
}
return (false);
}

/**
* Método que determina si el objeto es o no de tipo String
*
* @param Object o, el objeto a analizar
* @return boolean true si es String, false en caso contrario o si es null
*/
private static boolean isString(Object o) {
// si es null, es string
if (o == null) {
return (true);
}
return (String.class.isInstance(o));
}

} //fin de la clase


2.-En el validator-rules hago un validador. El msg lo extraerá del ApplicationResources respectivo. Nota: Quitar los espacios luego del '<'

< validator name="validateDCE"
classname="es.mipaquete.web.validator.MiValidation"
method="validateDCE"
methodParams="java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,
org.apache.struts.action.ActionMessages,
org.apache.commons.validator.Validator,
javax.servlet.http.HttpServletRequest"
depends=""
msg="errors.invalid.dce" >
< /validator>


3.-En el validation.xml, indico que campo del formulario está sometido a la validación. En el ejemplo muestro como colocar para el form. El key que coloco lo
extraerá del ApplicationResources respectivo. Nota: Quitar los espacios luego del '<'


< formset>
< form name="miFormBase">
< field property="maderistaForm.calificacionEmpresarial" depends="validateDCE">
< arg0 key="error.maderista.calificacionEmpresarial" name="validateDCE"/>
< /field>
< /form>
< /formset>


4.-En el ApplicationResources meto las variables necesarias:

errors.invalid.dce=\"{0}\" debe ser un DCE válido, ejemplo: 33/9999.
error.maderista.calificacionEmpresarial = Documento de Calificación Empresarial


5.-Queda colocar en struts que el validate=true y el input en el action correspondiente.

lunes, 16 de julio de 2007

Imprimiendo mensajes de error para relacionar con html:errors

Problema: Queremos imprimir mensajes de error para que sean tomados por la etiqueta

Soluciones: Dependiendo de la versión de struts que usemos valdrán unas u otras.

Solución con ActionMessages: Hago un método que redirigirá y con el código del almacenamiento del mensaje dentro. Puede variar el método, pero el registro del error es casi idéntico siempre.

protected ActionForward findSuccess(ActionMapping mapping, ActionForm arg1, HttpServletRequest request, HttpServletResponse arg3) {


if (this.getActionParameter(ExceptionCortasKeys.PARAM_ID_NO_SELECCIONADO)!=null){
String mensaje = new String("Mensaje de error a mostrar");
// registramos el error
ActionMessages errores = getErrors(request, true);
errores.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("idErrorGlobal", mensaje));
saveErrors(request, errores);
//redirijo a la página de input del mapeo de struts
return mapping.getInputForward();
}

return super.findSuccess(mapping, arg1, request, arg3);
}


Solución con ActionErrors:
Explicación idéntica que lo anterior, varía el tipo de mensajes, es decir, el registro del error, quedando así:

ActionErrors errors = getErrors(request, true);
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("global.princastexception", exception.getMessage()));
saveErrors(request, errors);

Mostrando pdf usando struts.

Problema: Queremos poner un enlace para que se llame un action y se muestre un pdf (típica ventana para abrir o descargar). El pdf nos viene en un array de bytes.

Solución: Desde la propia action que es llamada desde el enlace, colocaríamos el siguiente código:



try{
//obtengo el array de bytes del pdf
byte[] respuestaByte= this.miDelegate.getPDF();

//digo que es un pdf
response.setContentType("application/pdf");

//asigno el nombre del pdf, para cuando el usuario lo abra o descargue
response.setHeader("Content-Disposition",("attachment;filename=\"" +
nombrePDF+ ".pdf\""));

int longitud = respuestaByte.length;

//especifico el tamaño
response.setContentLength(longitud);

/*volcando a fichero*/
ServletOutputStream ouputStream = response.getOutputStream();

ouputStream.write(respuestaByte);

ouputStream.flush();

ouputStream.close();

}
catch(Exception e){
logger.error("No se ha podido regenerar correctamente el pdf");
}

jueves, 22 de marzo de 2007

Imprimir excepciones en código de jsp

Problema: Cuando una jsp nos está generando un error, y queremos saber cuál es, pero no mostrárselo al usuario.

Solución: (Quitar los espacios después de los '<')

Agregar en una tile, el pie siguiente...o colocar el código correspondiente en cada jsp que queramos lo planteado.


< %@ page isErrorPage="true" %>
< %@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %>
< %@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>

< !--
Información de errores JSP

< % if (exception != null) { %>
< pre><% exception.printStackTrace(new java.io.PrintWriter(out)); %>< /pre>
< % } else { %>
No hay ninguna excepcion visible, chequea los logs en busca del error
< % } %>
-->

viernes, 16 de febrero de 2007

Abrir automáticamente una impresión de una página html

Muchas veces al abrir una ventana queremos que se lance la ventana de impresión automáticamente, esto se consigue con un iframe oculto (accesibilidad=0).

1.-Función js para detectar el tipo de navegador, porque la impresión se lanzará de manera diferente (hace uso de la función para detectar el navegador que tengo en otro post):

/*Función que imprime el frame oculto*/
function imprimoFrame(){
var tipo = tipoNavegador();
if (tipo==1){
window.frames["popUpImpresion"].focus();
window.frames["popUpImpresion"].print();
}else{
if (tipo==2){
document.popUpImpresion.focus();
document.popUpImpresion.print();
}else{
if (tipo==3){
document.popUpImpresion.focus();
document.popUpImpresion.print();

}
}
}
}

2.-Coloco en mi página el iframe: (quitar el espacio luego del '<')

< iframe class="marcoOculto" src="/aplicacion/action/confirmPopUp" name="popUpImpresion" id="popUpImpresion" onload="imprimoFrame()">
Su navegador no soporta IFrame
< /iframe>


3.-La class marcoOculto de css tiene lo siguiente:

/*oculta un iframe, en realidad pone ancho y alto a 0*/
iframe.marcoOculto{
border:none;
width:0em;
height:0em;
}


4.-El action /aplicacion/action/confirmPopUp lo que hace es llevar a la tile aplicacion.respuestaHTML que en realidad es la página html a imprimir. En realidad, se podía haber colocado la página directamente, pero esta forma es más elegante.