Combos encadenados con Servlets y JQuery aplicando el MVC

Bueno A estrenar mi blog en Java México. Espero que sea de su agrado mi publicacion, en esta pagina, la verdd no soy muy experto como programador pero hacemos el intento. Bueno manos a la obra, primero definamos algunos conceptos:
MVC: Segun la wiki estilo de arquitectura que separa los datos de una aplicación la interfaz de usuario y la lógica de control en 3 componentes distintos.

Bien, Ahora Vamos a la pŕactica: Para ello Vamos a utilizar como ejemplo La creacion de unos combos encadenados de Paises y Ciudades.

CAPA DEL MODELO
Este parte del código viene dentro del paquete del modelo que seria en si la lógica de control

//Creacion del metodo para buscar Paises al realizar la consulta a la base de datos en el paquete del modelo
public ArrayList buscaPaises()  {
        //creacion del arraylist ciudades
        ArrayList Ciudades = new ArrayList();
        try {
            //Realizar la conexion a la base de datos
            //Obviamente con una Clase Conexion tambien en el paquete del modelo
            Conexion cnn = new Conexion();
            connection = cnn.getConnnection();
                 
            st = connection.createStatement();
            rs = st.executeQuery("select idpais,nombre from Paises");
            //iterar los resultados
            while (rs.next()) {
                Paises.add(rs.getString("idpais"));
                Paises.add(rs.getString("nombre"));
            }
           
        } catch (NamingException ex) {
            Logger.getLogger(Usuario.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SQLException e) {
            System.err.println("error " + e.getMessage());
        //se cierran la conexion y el Statement
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (st != null) {
                    st.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (Exception e) {
                System.out.println("Error en consulta");
                e.printStackTrace();
            }
        }
        //retornar el arrayList
    return Ciudades;
    }
//Creacion del metodo para buscar las ciudades al realizar la consulta a la base de datos en el paquete del modelo recibe como paramtro el iddel pais
public ArrayList buscaCiudades(int id)  {
        ArrayList Ciudades = new ArrayList();
        try {
            Conexion cnn = new Conexion();
            connection = cnn.getConnnection();
            st = connection.createStatement();
            rs = st.executeQuery("select idciudad,nombre from Ciudades where idpais=" + id);
            while (rs.next()) {
                Ciudades.add(rs.getString("idciudad"));
                Ciudades.add(rs.getString("nombre"));
            }
        } catch (NamingException ex) {
            Logger.getLogger(Usuario.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SQLException e) {
            System.err.println("error " + e.getMessage());
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (st != null) {
                    st.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (Exception e) {
                System.out.println("Error en consulta busquedaClave -->");
                e.printStackTrace();
            }
        }
        return Ciudades;
    }
}

CAPA CONTROLADOR:

//Servlet para formar la cadena en formato JSON para los Paises en el paquete controlador

public class Paises extends HttpServlet {
    String lista = new String("");
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            Usuario Consultar = new Usuario();
           //acceder al metodo buscaPaises             
            ArrayList Paises = Consultar.buscaPaises();
            if (Paises.size() != 0) {
                lista = "\"" + "Paises" + "\":" + "[";              
                for (int x = 0; x < Paises.size(); x=x+2) {
                    lista += "{" + "\"" + "id" + "\"" + ":"  + Paises.get(x).toString() +  "," +
                            "\"" + "TNAME" + "\"" + ":" + " \"" + Paises.get(x+1) + "\"" + "}" + ",";
                        //formar la cadena en formato JSON para enviarlo a la vista con jquery
                    }
                //quitar la ultima coma para parsear la cadena JSON
                lista = lista.substring(0, lista.length() - 1);
            } else {
                out.println("No se logro obtener datos");
            }
        } finally {
            out.println("{" + lista + "]}");
            out.close();
        }
    }

//Servlet para formar la cadne en formato JSON para las Ciudades en el paquete controlador
public class Ciudades extends HttpServlet {
    String lista = new String("");
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        response.addHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("pragma", "no-cache");
        response.addDateHeader("Expires", -1);
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        try {
            Usuario Consultar = new Usuario();
        //acceder al emtodo buscaCiudades con un parametro que seria el idciudad
            ArrayList Ciudades = Consultar.buscaCiudades(Integer.parseInt(request.getParameter("id").toString()));
     
                lista = "\"" + "Ciudades" + "\":" + "[";
                for (int x = 0; x < Ciudades.size(); x=x+2){
                    lista += "{" + "\"" + "id" + "\"" + ":"  + Ciudades(x).toString()  +
                            "," + "\"" + "nombre" + "\"" + ":" + " \"" + Ciudades.get(x+1) + "\"" + "}" + ",";
                }
                lista = lista.substring(0, lista.length() - 1);
            }
        } catch (Exception e) {
            System.out.println("Error en servlet:");
            e.printStackTrace();
        } finally {
            out.println("{" + lista + "]}");
            out.close();
        }
    }

CAPA VISTA

<script type="text/javascript">
//Observese que la respuesta viene del servlet Paises
$.getJSON("Paises",
    function(data){
        $.each(data.Paises, function(i,item){
            $("#idpaises").append("<option value='"+item.id+"'>"+item.TNAME+"</option>");
        });
    });

$(function(){
        //evento change parececido al onchange de javascript que cambia al seleccionar los Paises
    $("#idpaises").change(function(){
        //Observese que la respuesta viene del servlet Ciudades
        $.getJSON("Ciudades",{
                //evaluar el id de paises
            id: $(this).val(),
            ajax: 'true'
        },
        function(data){
                //limpiar el option value
            $("#idCiudades").html("");
            $.each(data.Ciuadades, function(i,item2){
                $("#idCiudades").append("<option value='"+item2.id+"'>"+item2.nombre+"</option>");
            });
        });
    });
});

</script
<body>
    // verficar que el id del select es el mismo  que en esta funcion de jquery $("#idpaises").change(function(){
 <select id="idpaises" style="width:200px" >
 <option>Selecciona Pais</option>
 </select>
 <select id="idCiudades" style="width:200px">
 <option>SeleccionaCIudad</option>
  </select>
</body>

Bueno obviamente falta cerrar las clases, e ingresar nuevas funciones en los servlets, además de la clase para la conexion a la base de datos. Pero bueno ojala sea de su interes mi publicacion muchas gracias por el espacio. Cualquier duda o correcion aquí estamos. Es bueno saber las opiniones buenas o malas de los demas.

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

bravo!

hola!
Aabo de leer tu artículo sobre Json, servlets y demás y me ha parecido muy bien, excepto una cosa que no he comprendido: como se integra la vista con una Jsp o similar? que código es ese que has puesto? perdona pero es aqui donde no entiendo cómo obtener los datos y mostrarlos al usuario.
Por cierto que creo que sería muy interesante que facilitaras el proyecto que sirve como demo para lo que has publicado en el artículo.
Nada más, muchad felicidades y ánimo con este tipo de artículos.
Salu2

Imagen de rodrigo salado anaya

en lo personal

Hola, a mi en lo personal, para usar JSON me gustan mucho las librerias:

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
etc...

las puedes usar agregando la libreria:
restlib_gfv3ee6

Imagen de ale_imp

Hola snatch perdon por falta

Hola snatch perdon por falta de tiempo no habia realizado lo que necesitabas pues mira el codigo que puse de lado de la vista solo se coloca entre los tags de html y javasccript como ya fue corregido recuerda descargarte la libreria JQuery y llamarla desde el jsp. Bueno hasta luego cuqlueir duda aqui estamos.

Imagen de fcodiaz

Bien! =D... interesante ejemplo

Bueno digamos que esta medio bien la división de las capas.. solo que en capa Modelo nunca debes de mandar imprimir, ni mostrar nada.. tampoco yo gestionaría las excepciones en esta capa, ya que a esta no le corresponde mostrar errores.. lo digo por los System.out.println(""); que tienes en tu capa de Modelo, con ese println estas mandando mostrar el mensaje directamente a la consola, una labor que le corresponde a la vista, en modelo podemos gestionar los errores pero tienen que responder generando excepciones o bien retornando valores, un Modelo nunca muestra un dato ni en consola ni en ningún lugar.. o retorna un resultado o genera excepciones que en la capa controlador tiene la labor de sanar e invocar la vista que le corresponde. la vista solo recibe variables y define como mostrarlas, ejemplo un JSP que solo tenga imprima en cierto lugares las variables que reciba, o una clase con un método que envié mensajes a la consola esa seria una vista pero en una vista nunca se hacen operaciones mas que mostrar información, el controlador recibe la información del usuario y gestiona que modelos instancia y que métodos ejecutar interpreta sus respuestas y envía los resultados a las vista la cual los muestra.

ahora la creación del JSON amm la designaría a la capa Vista ya que es la forma en como el servlet muestra la información.

Aquí entra a lo que me refiria de lo mal que creo que es fusionar los lados cliente y servidor, ya que yo considero Vista a la impresión del JSON ya que este es el resultado final de un request, y lo que estoy viendo en la web que pudo haber sido el resultado de la vista de otro request pero en este momento es un HTML muy aparte de lo que suceda en el servidor, aquí esto es otro asunto muy aparte.

snatch, aquí es donde se fusionan las vista, ya que JSON es un request aparte es otro proceso que se lanza posterior a la impresión del primer jsp que te mostraría el HTML desde el cual posteriormente con JavaScript y el uso de XHR mandas ejecutar otro request el cual es otro proceso independiente al primero, se toma la respuesta de este ultimo para mediante JS se manipular el DOM del HTML y mostrar la información obtenida. el html desde donde cargas el request del JSON incluso puede ser un HTML normal que no tubo por que ser la respuesta de un proceso en servlet o en JSP o en cualquier otra tecnología, estamos ablando que en este momento es un HTML común y corriente.

ejemplifico un poco como yo haría la división, no creo las clases con sintaxis correcta solo es para que te des una idea ;)

class Ciudad{
      public static ArrayList buscar();
}
class viewJSON{
       public void out(ArrList arregloInfo);
}
class ControlCliente{
     public void buscarCiudad(request,response)
}

vista : platilla.jsp

explico un poco a ver si se entiende..
en Ciudad yo crearía un clase que tuviera los dato para poder crear instancia de ciudad, su métodos para salvar elminar etc.. todos ellos o retornan datos true,false, string.. etc. o me generan exepciones que se devén de sanar en el controlador que usen la clase Ciudad.

en ControlCliente este sera mi unico servlet real, las demás pueden ser simples clases, de hecho la idea es que los modelos lo sean, para así poderlo utilizar en otros proyectos por ejemplo la misma clase te serivira para crear una aplicacion de escritorio sin tener que reescribir los modelos. en CotrolCliente es donde llamaría al objeto Static Buscar, lo dejo en estatic por que no es en si un método de un objeto Ciudad, sino que lo vero como que este metodo me retornaría muchos objetos Ciudad en el caso me retorna un ArrayList, una ves ejecutado el método y envió este ArrayList que obtuve de Modelo Cliente a mi clase viewJSON, el cual se encargaría de imprimir en formato JSON el ArrayList que le envió, y con esto termino la dinámica MVC de la petición del JSON con las ciudades.

ahora lo que pasa en JS es otra cosa, ya que aquí también podríamos usar un tipo MVC, aunque por ahora creo que la forma de "rellenar" tu select con jQuery es relativamente correcto, si no deseas complicarte un poco en lado cliente, aunque puedes ver los temas OOP en JS lo ideal (para mi) es que generaras un prototipo (class en JS) de Ciudad y en ella generar el Option y luego en un script que maneje instancia de este prototipo y los eventos dentro de la pagina ya viéndolo todoesto desde el cliente (programación en JS), mi teoria en esto es que si hacemos la programacion de esta forma nuestro lado cliente como servidor son independite de sierta forma, XHR nos sirve para alimentar y enviar información a un servidor http el cual no nos interesa mucho si procesara nuestra respuesta un servlet, php, jsp, asp, ruby.. o lo que sea en esto solo nos interesa la respuesta del servidor, y lo demás corre por parte del servidor trasparente al cliente. esta era la teria que avarcaria mi tesis para mi titulaciòn. pero ps ya no tube que hacer tesis.. me ofresieron otra forma mejor de titularme =D

un error que veo muy recurrente es ver el desarrollo en servidor con respuestas a click's o a eventos generados en el cliente.. si y no, ya que al dar yo click en un elemento del html se genera un evento pero este en el DOM. y la programación en lado servidor solo se rige por un evento.. request! (peticiones).

bueno espero que me alla explicado en cuanto al MVC y división de cliente y servidor, cualquier duda ps por aqui andamos ;)

www.devtics.com.mx

Imagen de fcodiaz

Otra cosilla que se me olvido

bueno se olvido comentarte, que es buena idea cambiar el tipo MIME de tu respuesta por application/json

response.setContentType("application/json;charset=UTF-8");

En lugar de :

response.setContentType("text/html;charset=UTF-8");

ya que este es el tipo mime de los JSON como lo estas haciendo tecnicamente estas sirviendo un HTML como respuesta, si cambias el mime a application/json no podras verlo directo en el explorador, para firefox hay una extencion para poderlo ver, lo bonito es que lo mapea como lo hace con los XML, de igual forma firebug te mapea el JSON y asì lo puedes analizar muy comodamente desde firebug ;)

por ejemplo aqui tengo una imagen donde genero un JSON desde php y envio la cabecera application/json, si envio text/html me muestra como si fuera un documento html y pues no es muy amigable de analizar asi,

http://tweetphoto.com/18706525

www.devtics.com.mx

Perdido

Soy nuevo en esto del MVC pero bueno aqui va mi duda el patron segun wikipedia especificalo siguiente:
Controlador: Este responde a eventos, usualmente acciones del usuario, e invoca peticiones al modelo y, probablemente, a la vista.

Si wikipedia esta en lo correcto ¿por que se le dota de un writer como el objeto out en el servlet ciudades? ¿No es eso trabajo de la capa V?

        response.setContentType("text/html;charset=UTF-8");
        response.addHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("pragma", "no-cache");
        response.addDateHeader("Expires", -1);
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
Imagen de fcodiaz

de hecho...

en efecto este es un error de ale_iimp y es una de las primeras observaciones que le hise

"System.out.println(""); que tienes en tu capa de Modelo, con ese println estas mandando mostrar el mensaje directamente a la consola, una labor que le corresponde a la vista, en modelo podemos gestionar los errores pero tienen que responder generando excepciones o bien retornando valores, un Modelo nunca muestra un dato ni en consola ni en ningún lugar"

en el caso del elemplo de ale_ilimp tiene dos formas de solucionar. como les digo se pueden gestionar los errores desde el modelo, mas que nada de validación y todo ese asunto, pero no se vale dar salida a los errores por ninguna vía, en su caso se genera una excepción que el cotrol gestionaría con un try/catch o bien se retorna el error para que la capa control designe por donde va a salir este error(que vista lo va a mostrar)

Imagen de ezamudio

println

Sin embargo, println es el debugger más versátil que existe. No debe quedarse eso ahí para producción pero creo que un println puede ir donde sea para una prueba, sobre todo cuando estás depurando algo.

Imagen de ale_imp

Gracias por las observaciones

En efecto solo println, lo estaba utilizando para ver si realizaba bien la consulta a la base de datos y verificar si estaba trayendo los valores correctos pero se me paso quitar esa linea, me gustaria si no es mucho pedir que me explicaras un poco más entonces como tratar las exepciones que no sean en el modelo. Gracias

Imagen de ezamudio

Manejo de excepciones

Realmente a lo que se refieren es que por ejemplo si estás cachando SQLException es porque vas a hacer algo al respecto, no nada más el println. Puede ser dejar algo en log de la aplicación y aparte regresar un código de error, o null... o si de plano no tienes por qué manejar la excepción pues no la cachas, pero entonces tienes que declararla en tu método.

En vez de esto:

public boolean metodo() {
  try{
    //hacer algo
    return true; //si todo sale bien
  } catch (SQLException ex) {
    //manejar la excepcion
  } finally {
    //liberar recursos (conexiones, etc)
  }
  return false;
}

Puedes hacer esto:

public void metodo() throws SQLException {
  try {
    //hacer algo
  } finally {
    //limpieza
  }
}

En el primer caso, puedes verificar si metodo() te devuelve true o false para saber si salió o no salió la operación; en el segundo caso, tienes que llamar metodo() dentro de un try-catch de SQLException y manejar la excepción ahí.

Imagen de fcodiaz

Ejemplificado... MVC

Bueno me tome el hobbie de hacer algo mas o menos para mostrar a lo que me refiero de generar exepciones en el Modelo para que esta sea gestionada en el Control y así este ultimo tiene el "Control" de sanar la excepción en el ejemplo simula un login en un servlet

1. Modelo (es una clase java)

/**
 *
 * @author Pakos
 * <a href="http://www.devtics.com.mx
" title="www.devtics.com.mx
">www.devtics.com.mx
</a> * 20/04/2010
 */

public class MUsuario {
    public MUsuario() {
        //este contructor lo dejo para crear usuario un nuevo usuario
        //q no esta guardado en la DB
    }
    MUsuario(int idUsr){
        //en este constructor me conectaria a la DB e iniciaria los valores
        //del usuario
    }
    MUsuario(String nick,String pass) throws Exception{
        //este seria un metodo para simular login, creo el usuario consultado
        //el nick y pass

        //-aki kodigo para conexion y consulta a la DB;
        String resNick="pako";
        String resPass="java";
        if(! (nick.equals(resNick)&&pass.equals(resPass)) ){
            throw  new Exception("Error Al Indetificar Usuario");
        }
       
    }
}

En el constructor que recibe el nick y el pass genere una excepción, la cual le indico que debe de sanar la clase que utilice MUsuario observa que creo un nuevo objeto Excpetion si el nick o el password no son iguale a resNick o resPass estas ultimas son una simulación del proceso conexión consulta recuperación de los datos.
si el login no es valido se crea la Exception uno de los constructores de la Clase Exception recibie un String el cual sera el Message de la exepcion, puedes investigar mas sobre la clase Exeption incluso puedes heredarla y crear tus propias variantes de excepciones según lo que requieras.

ahora vamos al las vistas, utilizo un par de jsp, muy parecido solo cambia el formato con css, pero cumple el objetivo de mostrar como el control decide que mostrar y la vista como y donde mostrarlo.

error.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"
        %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Pagina de Error</title>
        <link type="text/css" rel="stylesheet" href="css/error.css" media="all"/>
    </head>
    <body>
        <h1><%=request.getAttribute("strError")%></h1>
    </body>
</html>

welcome.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"
        %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Welcome <%=request.getAttribute("nick")%></title>
        <link rel="stylesheet" media="all" href="css/error.css"/>
    </head>
    <body>
        <h1 class="green">Welcome <%=request.getAttribute("nick")%></h1>
    </body>
</html>

css/error.css

body{
    background-image: url(bg.jpg);
}
h1{
    background-color: #ffffff;
    margin: 0 auto;
    margin-top: 40px;
    width:500px;
    padding: 50px;
    border:black solid 10px;
    display: block;
    text-align: center;
    color: red;
    -webkit-border-radius:  40px ;
    -moz-border-radius:  40px;
         border-radius:  40px;
}
h1.green{
    border-color:  #045500;
    font-family: 'Times New Roman',Times,serif;
    color: #0066ff;
    -moz-box-shadow: black 10px 5px 5px;
    -webkit-box-shadow: black 10px 5px 5px;
        box-shadow: black 10px 5px 5px;
        text-shadow:#CCCCCC 2px 1px 2px;
}

Estos archivos formarian nuestra capa Vista, observa que los JSP no tienen mas que el proceeso de imprimir variables en un determinado lugar del HTML de respuesta, el CSS se encarga de formatear la pagina y se separa del HTML del JSP así también se respetan la calidad de semántica en el HTML y el CSS cumple su función de formatear el documento. ya tenemos cubiertas nuestras capas M y V, ahora viene el Control, este si sera un servlet.

Login.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author Pakos
*  www.devtics.com.mx
* 20/04/2010
 */

public class Login extends HttpServlet {  
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
                String nick="pako";
                String pass="java";                
                new MUsuario(nick, pass);
                RequestDispatcher rd = request.getRequestDispatcher("welcome.jsp");
                request.setAttribute("nick",nick);
                rd.include(request, response);
        }catch (Exception ex) {                
            RequestDispatcher rd = request.getRequestDispatcher("error.jsp");
            request.setAttribute("strError",ex.getMessage());
            rd.include(request, response);
        }
        finally {
            out.close();
        }
    }
    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
}

Borre el codigo generado por netbeans, no tiene caso solo me interesa mostrar el processRequest, bueno observa que este es el Control, el decide que es lo que va hacer y maneja los Modelos de nuestro sistema, en este ejemplo crea una instancia de MUsuario y tal como lo marca la deficion de esta, si no se encierá en un try/catch o se deslinda de la responsabilidad de sanar el error con un throw se nos marcara un error, en este ejemplo nick y pass se simulan de igual manera en un ejemplo real se deverian de obtener del POST o del GET del request o hacer lo que necesites hacer para obtener los datos, se crea el constructor si el login no funciona se genera una excepcion la cual nos lleva al bloque catch donde sanaremos el error en este caso se manda llamar el jsp error.jps que es nuestra vista la cual se encarga de recuperar un atributo del request que se llama strError y mostrarlo, observa que antes se "settea" strError en el request y su valor es el getMessage del objeto ex. si todo funciona bien se le llamara a welcome.jsp.

y listo con eso tenemos ejemplificado nuestra capa C,.. con lo que tenemos M.V.C =).. y con esto demuestro que no es necesario un framework prefabricado para hacer MVC,que si faltan cositas por afinar por ejemplo no me gusta el como se pasan los valores al jsp, yo mandaria un mapa para solo tener una intrución, igual se podria generar un método "getJSP(Strr jsp,Object datos)" (siempre hay que buscar la forma de reciclar y hacer menos trabajo en el futuro) y hacer mas un poco mas elegante nuestra codificación pero siempre he dicho que esas cosita se van a finando en la marcha conforme vamos adquiriendo experiencia, esto no es mas que un ejemplo de como lograr MVC y para explicar un poquito el objetivo de cada una de las capas y como desde el Modelo sanar los errores aplicando excepciones,

y por ultimo aquí les dejo el proyecto para netbeans 6.8, esta configurado para correr en tomcat 6.0 y como siempre los ejemplos se ven mas bonitos en Firefox =P...

www.devtics.com.mx

Imagen de fcodiaz

Println en debug si pero no en producción

Si en println es el mejor debug que tenemos como dice ezamudio, por hay me critican por que por ejemplo al programar en JavaScript uso mucho el alert() que seria el equivalente al println en java =P, pero si pretendemos respetar el modelo si se tiene que ir una ves que la clase este terminada y libre de errores,

Aun perdido

Bueno al parecer la ultima vez que escribi no me di a entender muy bien asi que ahora con unas horas mas de estudio tratare de darme a entender.
En realidad mi duda no era torno a el System.out.print de hecho es de lo mas comun para debuggear mi duda en realidad es sobre el objeto out que describe este fragmento de codigo que tome de ale_imp

response.setContentType("text/html;charset=UTF-8");
        response.addHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("pragma", "no-cache");
        response.addDateHeader("Expires", -1);
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();

Si no mal entiendo eso practicamente es el encabezado de una jsp pero esto en realidad es un servlet parte del controlador de acuerdo como explica ale_imp, pese a que no veo que use el objeto out para imprimir algo en la pagina en otros ejemplos que he encontrado, es posible usarlo para imprimir html.
Ahora entonces de nuevo mi duda es ¿Por que dotar al controlador de un objeto capaz de imprimir html? mas aun sin usarlo o necesitarlo

Imagen de WinDoctor

Buenos programadores pero...

Con todo respeto, algunos de ustedes son excelentes programadores, solo que tienen una pesima ortografía y redacción que me costo trabajo leer y comprender algunos comentarios de este hilo. Por el bien de los que somos novatos y comprendamos lo que quieren decir, mejoremos nuestra ortografía y redacción!!! Después de todo la mayoría somos Ingenieros/Licenciados/Estudiantes con un supuesto nivel cultural.

Saludos :)

Imagen de fcodiaz

Comprate un Libro

@WinDoctor si gustas y requieres mayor calidad en ortografía y redacción, puedes consultar libros impresos que detrás traen una editorial y gente que cuida y trabaja esos detalle para satisfacer a la gente culta, en lugar de consultar a gente inculta, yo en lo personal soy alguien que con todo gusto me doy una vuelta si se algo lo comparto en un tiempo que me tomo para distraerme en mi trabajo, no tengo tiempo de estar revisando la ortografía y buscado la forma en como pasar el filtro de calidad en Ortografía y redacción, aunque acepto la critica, pero me caen mal esos comentarios de los gurus de la ortografía

Imagen de beto.bateria

Dos observaciones: - Crea una

Dos observaciones:
- Crea una clase llamada Pais que tenga los atributos idciudad y pais.
- La tarea de crear el JSON no pertenece al controlador, sino al modelo, es decir, el controlador ya debe de recibir la informacion necesaria para mandarla a la vista.

Imagen de AlexSnake

Excelente ejemplo.

Hace tiempo yo tuve que hacer algo similar, pero con el mvc de spring. Que mal que no vi tu ejemplo en ese momento me hubiera servido bastante.
Saludos

Imagen de jlopezjuy

excelente

ahora una consulta, como se aria con struts???? cargar los combos anidados y refrescarlos con jquery??? sin usar Struts2-jquery....