7. JADE y otras Tecnologías

7.1 Integración de Jade y Servlets

7.1.1 Introducción a los servlets

7.1.2 Introducción al paquete jade.wrapper.gateway

7.1.3 Integrar Servlet y JADE

7.2 Manual configuración Eclipse y tomcat v6.0

7.3 Integración de JADE y JESS

7.3.1 Introducción a JESS

7.3.2 Lenguaje JESS

7.3.3 Integrar JESS en JADE

7.3.4 Ejemplo práctico

7.4 Ejercicio



arriba.png

7.1 Integración de JADE con servlet (clase JadeGateway)

En este punto trataremos de explicar qué es un servlet y como se puede conectar a JADE por medio de la clase JadeGateWay.

arriba.png

7.1.1 Introducción a los servlets

Los servlets son objetos que corren dentro del contexto de un contenedor de servlets (ej: Tomcat) y extienden su funcionalidad. También podrían correr dentro de un servidor de aplicaciones (ej: OC4J Oracle) que además de contenedor para servlet tendrá contenedor para objetos más avanzados como son los EJB (Tomcat sólo es un contenedor de servlets).
La palabra servlet deriva de otra anterior, applet, que se refería a pequeños programas escritos en Java que se ejecutan en el contexto de un navegador web. Por contraposición, un servlet es un programa que se ejecuta en un servidor.
Un servlet es un objeto que se ejecuta en un servidor o contenedor JEE, fue especialmente diseñado para ofrecer contenido dinámico desde un servidor web, generalmente es HTML.
Los servlets forman parte de JEE (Java Enterprise Edition), que es una ampliación de JSE (Java Standard Edition).
Un servlet es un objeto Java que implementa la interfaz javax.servlet.Servlet o hereda alguna de las clases más convenientes para un protocolo específico (ej: javax.servlet.HttpServlet). Al implementar esta interfaz el servlet es capaz de interpretar los objetos de tipo HttpServletRequest y HttpServletResponse quienes contienen la información de la página que invocó al servlet.
La interface Servlet declara los métodos que se debe implementar:
void
destroy()
Es llamado por el contenedor del servlet para finalizar el servlet.
ServletConfig
getServletConfig()
Devuelve un objeto ServletConfig que contiene los parámetros de inicialización del sevlet
String
getServletInfo()
Devuelve información del servlet como el autor,versión ...etc.
void
init(ServletConfig config)
Es llamado por el contenedor de servlets para poner en funcionamiento un servlet
void
service(ServletRequest req, ServletResponse res)
Es llamado por el contenedor de servlets para permitir al servlet contestar a una petición

Nosotros utilizaremos la clase javax.servlet.HttpServlet que nos permitirá sobreescribir los métodos necesarios para la correcta inicialización,destrucción y proceso de peticiones tanto get como post desde un formulario de una página html. Los métodos son los siguientes:
  • doGet, para el proceso de peticiones get
  • doPost, para el proceso de peticiones post
  • doPut, para el proceso de peticiones put
  • doDelete, para el proceso de peticiones delete
  • init and destroy, manejo de recursos que serán útiles en la vida del servlet
  • getServletInfo, provee información sobre el servlet como autor,versión...


Ejemplo se Servlet

En este sencillo ejemplo mostraremos las partes básicas de un sencillo Servlet que recibe una petición get de una página html y muestra la hora de la petición y un campo nombre .

index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Ejemplo de Servlet/title>
  </head>
 
  <body id="page">
      <br><h1>Ejemplo de Servlet</h1><br>
      <HR>
    <form id="operationBox" method="get" action="EjemploServlet">
        Nombre:  <input type="text" name="nombre"/><br>
        <input type="submit" value="Enviar"></input>
    </form>
 
  </body>
</html>

EjemploServlet.java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.io.*;
/**
 * Servlet implementation class for Servlet: EjemploServlet
 *
 */
 public class EjemploServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
   static final long serialVersionUID = 1L;
 
 
    public EjemploServlet() {
        super();
    }
 
 
    public void destroy() {
 
        Date ahoraDestroy = new Date();
        System.out.println ("\n\nMensaje lanzado desde el destroy");
        System.out.println ("El Servlet se ha parado: "+ahoraDestroy +"\n\n");
        super.destroy();
    }
 
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
        //Captura de parámetro mediante el método String getParameter(String name)
        String nombre=request.getParameter("nombre");
 
        //Asignación a la respuesta html que va a generarse
        response.setContentType("text/html");
 
        //Obtención del objeto que escribe la respuesta. Pertenece a java.io
        PrintWriter out=response.getWriter();
 
        //Generación de la respuesta html
        out.println("<html>");
        out.println("<head><title>Primer servlet</title></head>");
        out.println("<body>");
        out.println("<h1>Hola, "+nombre+"</h1>");
        out.println("<h1>"+getServletName()+" funcionando</h1>");
        Date ahoraGet = new Date();
        out.println ("La fecha en el momento de la petición get es: "+ahoraGet);
        out.println("</body>");
        out.println("</html>");
    }
 
    public void init() throws ServletException {
 
        Date ahoraInit = new Date();
        System.out.println ("\n\nMensaje lanzado desde el init");
        System.out.println ("El Servlet se ha iniciado: "+ahoraInit +"\n\n");
        super.init();
    }
}

arriba.png

7.1.2 Introducción al paquete jade.wrapper.gateway


El paquete principal de Jade que utilizaremos para la comunicación con el servlet es jade.wrapper.gateway, que incluye las clases:

JadeGateway, GatewayAgent, GatewayBehaviour

JadeGateway: Esta clase sera nuestro punto de entrada, ya que nos provee de una pasarela para poder conectar código no JADE con sistemas multiagente basados en JADE. Esta pasarela mantendrá un agente (de la clase GatewayAgent) que será el que se comunique directamente con nuestro servlet. La activación / terminación de este agente se gestiona completamente mediante la clase JadeGateway, no hace falta que el programador se preocupe por ello.
JadeGateway permite dos formas de implementar la pasarela que utilizaremos para la comunicación.
La primera (y la que usaremos en los ejemplos) es crear un agente que derive de GatewayAgent. De esta forma, tendremos que implementar dos métodos:
- processCommand: Establecerá la comunicación, recibiendo por parámetro un objeto que contiene la información que necesitamos para realizar las operaciones oportunas.
- releaseCommand: Una vez se hayan completado las operaciones a realizar por el sistema multiagente, se devolverá el objeto al servlet, con la información de respuesta que se estime oportuna. Este ciclo de comunicación podrá repetirse hasta que terminemos el agente de pasarela que hemos creado con JadeGateway.shutdown().

La segunda consiste en implementar un comportamiendo que derive de la clase GatewayBehaviour, para que un agente propio (sin que tenga que derivar de GatewayAgent) pueda funcionar como pasarela. Para ello añadiremos a nuestro agente una instancia de un comportamiento que derive de GatewayBehaviour, como decíamos antes. Este comportamiento también tendrá que implementar los métodos que vimos antes, processCommand y releaseCommand.

El agente que actúe como pasarela, será iniciado por medio de la clase JadeGateway desde el servlet, por medio del método JadeGateway.init(). Este método recibirá como parámetros el agente (el nombre de la clase que implementa el agente, no el nombre del agente en sí) y una serie de propiedades que definirán parámetros como el Host y el Puerto en el que se está ejecutando la plataforma Jade con la que nos queremos comunicar. Una vez iniciado, realizaremos la comunicación por medio del método JadeGateway.execute(), al que le pasaremos el objeto que se recibirá en el agente pasarela por medio de processCommand().
Finalmente, si queremos terminar nuestro agente pasarela, utilizaremos el método JadeGateway.shutdown().


arriba.png

7.1.3 Integrar Servlet y JADE


Para ver como se integran Servlets y JADE veremos dos ejemplos, en el primero de ellos validaremos un nombre de usuario y contraseña contra JADE y en el segundo enviaremos un saludo a un agente que estará dentro de la plataforma JADE.

arriba.png

7.1.3.1 Ejemplo ServletValidar


En este ejemplo utilizaremos una página html para enviar un formulario al servlet con un nombre de usuario y contraseña, el servlet será el encargado de conectarse con JADE através del GateWayAgent. El GateWayAgent tandrá dos funciones, la primera será la de ser el nexo entre el Servlet y JADE y la segunda la de validar al usuario con unos valores que tiene almacenados como predeterminados que serán usuario="root", contraseña="root".
Los elementos del ejemplo serán los siguientes:
  • index2.html: será la página html encargada de mandar la petición con los datos del usuario al servlet
  • ServletValidar.java: será el encargado de procesar la petición de index2.html y devolver una respuesta
  • Usuario.java: será la clase que transportará los datos del usuario y la respuesta del GateWayAgent
  • MiAgenteGateWay.java: clase deriva de GateWayAgent y sirve de pasarela entre el servlet y JADE.

A continuación mostramos un pequeño ejemplo con los pasos más importantes a realizar:

ServletValidar.jpg
Código de las respectivas clases y página html:

index2.html
<!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=ISO-8859-1">
<title>Ejemplo2 JadeGateWay</title>
</head>
<body>
    <br><h1>Ejemplo de uso de JadeGateWay</h1><br>
    <HR>
    <form id="operationBox" method="post" action="ServletValidar">
        <input type="hidden" name="accion" value="validar"/>
        Nombre:  <input type="text" name="nombre"/><br>
        Contraseña: <input type="password" name="contraseña"/><br><br>
        <input type="submit" value="Validar"></input>
        <input type="reset" value="Borrar"/>
    </form>
</body>
</html>

ServletValidar.java
package servlet;
 
/****************************************************************
 
Servlet que recibe las peticiones del usuario o de la página web
 
*****************************************************************/
 
import jade.core.Profile;
import jade.core.ProfileImpl;
import jade.core.Runtime;
import jade.wrapper.AgentController;
import jade.wrapper.ContainerController;
import jade.wrapper.gateway.JadeGateway;
 
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
import usuario.Usuario;
 
 
public class ServletValidar extends HttpServlet{
 
    static final long serialVersionUID = 1L;
 
    //la peticiones get son tratadas como las post
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
 
        doPost(request,response);
    }
 
 
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
 
        //obtenemos la acción a realizar
        String nombreAccion = request.getParameter("accion");
 
        if (!nombreAccion.equals("validar"))    {
            response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE);
            return;
        }else{
            //creamos el objeto que enviaremos a JADE
            Usuario usuario = new Usuario();
            usuario.setUsuario(request.getParameter("nombre"));
            usuario.setContraseña(request.getParameter("contraseña"));
 
            //mandamos el usuario al agente GateWayAgent de JADE
            try    {
                JadeGateway.execute(usuario);
            } catch(Exception e) { e.printStackTrace(); }
 
            //creamos la salida del servlet
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();
 
            out.print("El usuario es:"+usuario.getUsuario()+"<br>");
 
            out.print("Contestación:    "+usuario.getMensaje()+"<br>");
 
            out.print("<br/><a href='index2.html'> Volver a validar </a>");
 
            out.flush();
            out.close();
 
        }
    }
 
    //método que se invoca al cargarse el servlet en el contenedor de servlets
    public void init() throws ServletException {
 
        //Establecemos qué clase será la GateGayAgent
        JadeGateway.init("agentes.MiAgenteGateWay",null);
 
    }
}
 

Usuario.java
package usuario;
 
/*****************************************************************
 
La clase Usuario es el canal de comunicación entre AgenteGateWay y el ServletGateWay
 
*****************************************************************/
 
public class Usuario implements java.io.Serializable {
 
    private String usuario = new String("");
    private String contraseña = new String("");
    private String mensaje = new String("");
 
    public String getMensaje() {
        return mensaje;
    }
 
 
    public void setMensaje(String mensaje) {
        this.mensaje = mensaje;
    }
 
 
    public String getUsuario() {
        return usuario;
    }
 
 
    public void setUsuario(String usuario) {
        this.usuario = usuario;
    }
 
 
    public String getContraseña() {
        return contraseña;
    }
 
 
    public void setContraseña(String contraseña) {
        this.contraseña = contraseña;
    }
 
 
    public Usuario()    {
 
    }
 
}

MiAgenteGateWay.java
package agentes;
 
/*****************************************************************
 
Este agente recibe usuario y contraseña y los valida
 
*****************************************************************/
 
import usuario.Usuario;
 
import jade.core.AID;
import jade.core.behaviours.OneShotBehaviour;
import jade.core.behaviours.CyclicBehaviour;
import jade.domain.AMSService;
import jade.domain.FIPAAgentManagement.AMSAgentDescription;
import jade.domain.FIPAAgentManagement.SearchConstraints;
import jade.lang.acl.ACLMessage;
import jade.wrapper.gateway.*;
 
 
import java.util.Properties;
 
public class MiAgenteGateWay extends GatewayAgent {
 
    Usuario usuario = null;
 
 
 
    protected void processCommand(java.lang.Object obj) {
 
        //comprobamos que el objeto recibido sea un usuario
        if (obj instanceof Usuario)    {
            usuario = (Usuario)obj;
 
            //comprobamos que el usuario y contraseña las predefinidas
            if (usuario.getUsuario().equals("root")
                    && usuario.getContraseña().equals("root")){
                usuario.setMensaje(" Válido ");
            }else{
                usuario.setMensaje(" NO Válido");
            }
 
            //devolvemos el objeto usuario al servlet con la autentificación
            releaseCommand(usuario);
 
        }
 
    }
 
    public void setup()
    {
        super.setup();
    }
 
}


arriba.png

7.1.3.2 Ejemplo ServletGateWay


En este ejemplo utilizaremos una página html para enviar un formulario al servlet con una acción "enviarmensaje", el servlet será el encargado de elegir la acción adecuada que estará almacenada en una tabla hash <clave,AccionXXX> donde acción es el tipo de acción a realizar (en este caso "enviarmensaje") y AcciónXXX será un objeto que permitira realizar dicha acción. Este objeto AcciónXXX será el encargado de crear el mensaje a enviar por medio de la clase Mensaje.java y enviárselo al GateWayAgent. El GateWayAgent recibirá ese mensaje, construirá un mensaje ACL y se lo enviará al AgenteSaludo que le contestará con otro mensaje ACL. El GateWayAgent devuelve la contestación al Servlet (al objeto AcciónEnviarMensaje ) y este la muestra en el navegador.

Los elementos del ejemplo serán los siguientes:
  • index.html: será la página html encargada de mandar la accioón "enviarmensaje" al servlet
  • ServletGateWay.java: será el encargado de procesar la acción a realizar y divolver una respuesta que le llegará desde JADE
  • Acción.java: interfaz genérica para todas las posibles acciones del servlet, define un método enviar de tal forma que todas las acciónes serían invocadas de la siguiente forma : AcciónXXX.enviar(...);
  • AccionEnviarMensaje.java: clase que crea un mensaje predeterminado y lo envía y muestra la respuesta de JADE.
  • MiAgenteGateWay.java: clase deriva de GateWayAgent y sirve de pasarela entre el servlet y JADE. Además se encarga de enviar un mensaje ACL al AgenteSaludo y procesar su contestación enviándola de vuelta al Servlet.
  • AgenteSaludo: clase que implementa un agente que procesa un mensaje ACL y devuelve una contestación predefinida.

A continuación mostramos un pequeño ejemplo con los pasos más importantes a realizar:

ServletGateWay.jpg


Código de las respectivas clases y página html:

index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Ejemplo de uso de JadeGateWay</title>
  </head>
 
  <body id="page">
      <br><h1>Ejemplo1 de uso de JadeGateWay</h1><br>
      <HR>
      <img src="buzon.gif" WIDTH=200 HEIGHT=200 border=2><br><br>
    <form id="operationBox" method="get" action="ServletGateWay">
        <input type="hidden" name="accion" value="enviarmensaje"/>
        <input type="submit" value="Mandar Mensaje"></input>
    </form>
 
  </body>
</html>

ServletGateWay.java
package servlet;
 
/****************************************************************
 
Servlet que recibe las peticiones del usuario o de la página web
 
*****************************************************************/
 
import jade.core.Profile;
import jade.core.ProfileImpl;
import jade.core.Runtime;
import jade.wrapper.AgentController;
import jade.wrapper.ContainerController;
import jade.wrapper.gateway.JadeGateway;
 
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
import enviarmensaje.*;
import mensaje.Mensaje;
 
import java.util.*;
import jade.util.leap.Properties;
 
public class ServletGateWay extends HttpServlet {
 
    static final long serialVersionUID = 1L;
    Hashtable acciones = null;
 
    //las peticiones get son tratadas como las post
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
 
        doPost(request,response);
    }
 
 
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
 
 
        //obtenemos el valor del campo oculto accion
        String nombreAccion = request.getParameter("accion");
 
        if (nombreAccion == null)    {
            response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE);
            return;
        }
 
        //hacemos que el objeto implemente la interfaz acción
        //para que pueda utilizar los objetos HttpServletRequest y HttpServletResponse
        Accion accion = (Accion) acciones.get(nombreAccion);
        if (accion == null)    {
            response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
            return;
        }
 
        //ejecutamos la acción
        accion.enviar(this, request, response);
 
    }
 
    /**
     * Initialization of the servlet. <br>
     *
     * @throws ServletException if an error occure
     */
    public void init() throws ServletException {
 
        //creación de la tabla hash que contendrá el objeto AccionEnviarMensaje
        acciones = new Hashtable();
 
        //insertamos el objeto con clave su clave en la tabla
        acciones.put("enviarmensaje",new AccionEnviarMensaje());
 
        //enlace con el agente GateWay de JADE
        JadeGateway.init("agentes.MiAgenteGateWay",null);
 
    }
 
}


Accion.java
package enviarmensaje;
 
/*****************************************************************
 
Interface genérica para el servlet
 
*****************************************************************/
 
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
 
public interface Accion {
 
     public void enviar(HttpServlet servlet, HttpServletRequest request, HttpServletResponse response)
         throws IOException, ServletException;
 
}


AccionEnviarMensaje.java
package enviarmensaje;
 
/*****************************************************************
 
La clase AccionEnviarMensaje sale fuera del servlet y envía el mensaje al AgenteGateWay
 
*****************************************************************/
 
import jade.wrapper.gateway.JadeGateway;
 
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import mensaje.Mensaje;
 
public class AccionEnviarMensaje implements Accion {
 
    public void enviar(HttpServlet servlet, HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException    {
 
 
        // creamos un mensaje con un destinatario y contenido predefinido
        Mensaje mensaje = new Mensaje();
        mensaje.setReceiver("AgenteSaludo");
        mensaje.setMessage("Hola querido amigo, ¿cómo estás?");
 
        try    {
            //accedemos a JADE via JadeGateWay e esperamos la contestación
            JadeGateway.execute(mensaje);
        } catch(Exception e) { e.printStackTrace(); }
 
        //creamos la salida
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
 
        //imprimimos la contestación recibida de JADE
        out.print("¡El mensaje ha sido enviado!<br/>");
        out.print("Contestación:"+mensaje.getMessage()+"<br>");
        out.print("<br/><a href='index.html'> Volver a enviar </a>");
 
        out.flush();
        out.close();
 
    }
 
}
 


Mensaje.java
package mensaje;
 
/*****************************************************************
 
La clase Mesaje es el canal de comunicación entre AgenteGateWay y el ServletGateWay
 
*****************************************************************/
 
public class Mensaje  implements java.io.Serializable {
 
    private String message = new String("");
    private String receiver = new String("");
 
    public String getMessage()    {
              return message;
    }
 
    public void setMessage(String str)    {
        message=str;
    }
 
    public String getReceiver()    {
        return receiver;
    }
 
    public void setReceiver(String receiver)    {
        this.receiver=receiver;
    }
 
    public Mensaje()    {
 
    }
 
}

MiAgenteGateWay.java
package agentes;
 
/*****************************************************************
 
Este agente recibe el mensaje y se lo envía al agente AgenteSaludo
 
*****************************************************************/
 
import mensaje.Mensaje;
 
import jade.core.AID;
import jade.core.behaviours.OneShotBehaviour;
import jade.core.behaviours.CyclicBehaviour;
import jade.domain.AMSService;
import jade.domain.FIPAAgentManagement.AMSAgentDescription;
import jade.domain.FIPAAgentManagement.SearchConstraints;
import jade.lang.acl.ACLMessage;
import jade.wrapper.gateway.*;
 
public class MiAgenteGateWay extends GatewayAgent {
 
    Mensaje mensaje = null;
 
    //método que se ejecuta cuando se invoca JadeGateWay.execute(objeto) en el servlet
    protected void processCommand(java.lang.Object obj) {
 
        if (obj instanceof Mensaje)    {
 
            mensaje = (Mensaje)obj;
 
            ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
            msg.addReceiver(new AID( mensaje.getReceiver(), AID.ISLOCALNAME) );
            msg.setContent(mensaje.getMessage());
            send(msg);
        }
 
    }
 
    public void setup()
    {
        //Es perando por la respuesta de AgenteSaludo
        addBehaviour(new CyclicBehaviour(this)
        {
             public void action() {
 
                ACLMessage msg = receive();
 
                if ((msg!=null)&&(mensaje!=null))    {
                    mensaje.setMessage(msg.getContent());
                    //se devuelve la respuesta en el objeto mensaje al servlet
                    releaseCommand(mensaje);
                } else block();
             }
        });
 
        super.setup();
    }
 
}
 



AgenteSaludo.java
package agentes;
 
/*****************************************************************
 
Agente que contesta a los mensajes que le llegan con un saludo
 
*****************************************************************/
 
 
import jade.core.Agent;
import jade.core.behaviours.*;
import jade.lang.acl.*;
 
import jade.domain.DFService;
import jade.domain.FIPAAgentManagement.*;
import jade.domain.FIPAException;
 
public class AgenteSaludo extends Agent
{
 
    protected void setup()
    {
 
        // Comportamtiento a la espera de un mensaje
        addBehaviour(new CyclicBehaviour(this)
        {
            public void action()
            {
                ACLMessage msg = receive();
                String content= "";
 
 
                if (msg!=null) {
                    //rellenamos el contenido de la contestación
                    content=
                    "<br/> - " + myAgent.getLocalName() + " recibí: " + msg.getContent()+
                    "<br/> - " + myAgent.getLocalName() + " envío: " + "Yo estoy bien , ¿y tú?";
 
                    ACLMessage reply = msg.createReply();
                    reply.setPerformative( ACLMessage.INFORM );
                    reply.setContent(content);
                    send(reply);
                    System.out.print(content);
                }
                else block();
            }
        });
 
    }
 
     protected void takeDown()
       {
          try { DFService.deregister(this); }
          catch (Exception e) {}
       }
}
 
 




7.2 Manual configuración Eclipse y tomcat v6.0


Descarga Manual [PDF]

Descarga de programas:
Eclipse: http://sing.ei.uvigo.es/~lipido/DS1011/downloads/eclipse-jee-galileo-
SR2-win32.zip
Enlace alternativo Eclipse:
http://www.eclipse.org/downloads/packages/release/galileo/sr2
Apache Tomcat 6 : http://tomcat.apache.org/download-60.cgi
PASOS:
1.-

1.png

2.-




3.- El directorio lo guardamos en una carpeta dentro de C:/jade..Seleccionamos Apache Tomcat 6.0 su directorio de instalacion con jre6.Finish

3.png

4.- Jade -- propiedades -- Java Buid Path-- Libraries -- Add External JARs y seleccionamos en c:/jade/lib el archivo jade.jar

4.png

5.- En Java Resources :src-- New Packaged (agentes, servlets,usuario)

5.png

6.- En Agente-- new-- class y le damos el nombre MiAgenteGateWay. Lo mismo con servlet usuario pero con nombre Usuario.
6.png

7.- En servlet-- new--servlet con nombre: ServletValidar y Finish

7.png

8.png


8.- Cogemos los codigos correspondientes de la pagina http://programacionjade.wikispaces.com/OtrasTecnologias y lo pegamos en donde corresponde:

9.- A continuación creamos el formulario en WebContent--new--html page con nombre: “index2”
Y le añadimos tambien el codigo de la web



10.- Seleccionamos nuestro proyecto (jade) y le damos al boton Run As y seleccionamos Run on Server .

9.png

10.png

12.- Cerramos la ventana que se abre y le damos a stop en el servidor.
11.png


13.-Pasamos a Crear nuestro JAR, para eso vamos a FileExport y seleccionamos Java; JAR file:

12.png


Le damos a Next y seleccionamos TAN SOLO agentes y usuario de la carpeta src y Build>classes y del recuadro derecho seleccionamos .classpath y .project
Además le damos un nombre, y se guarda en C:/jade/lib
A continuación Next. Next y Finish. Si nos da una advertacia le damos a OK


13.png

14.- Ejecutamos el interfaz grafico desde consola : java jade.Boot –gui
14.png


15.- Volvemos a eclipse, y asegurandonos que el servidor TomCat esta parado,seleccionamos nuestro proyecto y le damos a Run y Run configurations.


15.png



16.- Una vez ahí, le damos TomCat v6.0 y la pestaña classpath y en user entries Add External Jars
16.png

17.-Añadimos de la carpeta c:/jade/lib el archivo jade.rar y el creado por nosotros. A Continuacion Apply>Run

18.- Con esto estará configurado. Para probarlo entramo desde el navegador en la direccion http://localhost:8080/jade/index2.html
Tendremos un formulario, para que sea correcto debemos introducir root/root, para cualquier otro caso será no valido.
17.png

18.png

arriba.png

7.3 Integración de JADE y JESS

En este punto se tratará de ver cómo puede ayudar JESS a los agentes inteligentes utilizando la plataforma JADE.


arriba.png

7.3.1 Introducción a JESS

JESS (Java ExpertSystem Shell) es un lenguaje de programación basado en CLIPS. Fue creado por Ernest Friedman-Hill de Sandia National Laboratories en Livermore, CA. Su funcionamiento se basa en reglas y usa el algoritmo Rete.

Se puede usar de dos modos:
  • Por un lado se puede usar como un Sistema Experto (Sistema Basado en Conocimiento). Un Sistema Experto ejecuta ciertas reglas (definidas por el programador) sobre el conocimiento que se tiene. Este uso se aplica a los agentes inteligentes, por lo que es donde profundizaremos más.
  • Por otro lado, JESS se ha escrito en JAVA y se puede integrar perfectamente en él accediendo directamente en sus clases y librerías para conseguir un desarrollo más rápido de las aplicaciones.

Un Sistema Experto es un Sistema Basado en Conocimiento con información precisa de un dominio y con capacidad de aprendizaje sobre él y que llega a trabajar de forma similar a una persona especializada en ese dominio. Está formado por:
  • Base de conocimientos (BC): contiene conocimiento modelado extraído del diálogo con el experto.
  • Base de hechos (BH) (Memoria de trabajo): contiene los hechos sobre un problema que se ha descubierto durante el análisis y pueden ir aumentando a medida que se descubran nuevos hechos en los ciclos de inferencia.
  • Motor de inferencia: modela el proceso de razonamiento humano. Es el que decide qué reglas de inferencia ejecutar siguiendo los pasos de un algoritmo.
  • Módulos de justificación: explica el razonamiento utilizado por el sistema para llegar a una determinada conclusión.
  • Interfaz de usuario: es la interacción entre el Sistema Experto y el usuario, y se realiza mediante el lenguaje natural.

sistExperto.JPG


arriba.png

7.3.2 Lenguaje JESS


En JESS como en cualquier otro lenguaje podemos encontrar elementos básicos como palabras reservadas, variables locales o globales, funciones y estructuras como if-then, while, foreach, for, try-catch,... Y cuyo funcionamiento es bastante similar a java.

JESS trabaja en base a 3 puntos clave:
  • Hechos: son la forma que utiliza JESS para representar el conocimiento.
  • Reglas: nos indican la acción que se debe llevar a cabo cuando surge una determinada condición.
  • Preguntas: se utilizan para obtener respuestas.

A continuacíon nos centraremos en la descripción de la parte más interesante de JESS, las reglas. Para intentar mostrar la utilidad de JESS.

REGLAS

Una regla sigue la estructura IF-THEN. Se construye a partir del constructor (defrule):
//(defrule nombreRegla (condición) => (acción))//
Donde condición son una serie de patrones que se usan para encontrar hechos de la Base del Conocimiento y acción son llamadas a funciones. El nombre de una regla (nombreRegla) es único, si se crea otra regla con el mismo nombre se sobrescribe la anterior.

Una regla se activa cuando todas sus condiciones se cumplen y está activo su motor de arranque. Para activar el motor de arranque hay que ejecutar (run). Por ejemplo, la siguiente regla indica que si la vivienda está vacía, las luces deben estar apagadas:

//(defrule apagarLuces
(and
(vivienda vacia)
(luz encendida)
)
=>
(printout t "La vivienda esta vacia. Las luces deben estar apagadas." crlf)
(retract-string "(luz encendida)")
(assert (luz apagada))
)//
 

//Jess> (assert (vivienda vacia))  //Hecho
 <Fact-0>
Jess> (assert (luz encendida))   //Hecho
 <Fact-1>
Jess> (run)
 La vivienda esta vacia. Las luces deben estar apagadas.
 1//
 

Patrones Básicos en las Reglas

La condición de una regla puede estar compuesta por varios patrones (como se ve en el ejemplo anterior).
Un patrón puede ser:
  • Un valor.
  • Una variable.
  • : seguido de la llamada a una función. Se cumple cuando la función devuelve TRUE.
  • = seguido de la llamada a una función. Es el valor que devuelve la función.
  • Puede incluir ~ (negación), & (AND) o | (OR) entre las variables.

Se puede poner una variable sin su nombre, sólo con ?, pero en el caso de que se nombre una sola vez en toda la regla.
También se puede poner una variable multicampo, que empieza con $?.

Ejemplos de patrones:

(noA ?x&~a): variables que no sean ‘a’.
(diferentes ?x &~?y): ?x y ?y tienen valores distintos.
(iguales ?x ?x): los dos parámetros tienen el mismo valor.
(mayor ?x&:(> ?x 1000)): el valor es mayor que 1000.
(finSemana sabado|domingo): el campo debe contener uno de esos valores.
(hijos $?padre): y después se podría crear una lista: (paco pepe luis).

Otros patrones
  • OR
    Se usa cuando una regla se puede activar de distintos modos, es decir cumpliéndose distintos patrones. Ejemplo: hoy será fin de semana si es sábado o domingo:
//(defrule finDeSemana
(or
(hoyEs sabado)
(hoyEs domingo)
)
=>
(printout t "Hoy es fin de semana." crlf)
)//
 

  • AND
    En este caso se tienen que cumplir todos los patrones. Puedes hacer combinaciones anidadas de AND y OR. Por ejemplo, una mujer es abuela de un niño si tiene algún hijo que sea su padre o si tiene alguna hija que sea su madre:
//(defrule abuela
(or
(and
(madre-de (madre ?h1) (hijo ?x))
(padre-de (padre ?x) (hijo ?h2))
(mujer ( nombre ?h1))
)
(and
(madre-de (madre ?h1) (hijo ?x))
(madre-de (madre ?x) (hijo ?h2))
(mujer (nombre ?h1))
)
)
=>
(printout t ?h1 " es abuela de " ?h2 crlf)
(assert(abuela ?h1 ?h2))
)//
  • NOT
    Se utliza cuando la condición de activación es que no se cumpla un patrón: (not (patrón)). Ejemplo:
//(defrule SemanaLaboral
 (and
  (not (hoyEs sabado))
  (not (hoyEs domingo))
 )
 =>
  (printout t "Estamos trabajando." crlf)
)//
  • OTROS
    salience: da prioridad a las reglas.
    test: evalúa condiciones.
    unique: indica que sólo puede haber un hecho que satisfaga ese patrón.
    exist: comprueba si hay algún hecho que cumpla el patrón (no es posible combinarlo con test).

arriba.png

7.3.3 Integrar JESS en JADE


JESS se puede integrar en JAVA y acceder a sus clases y librerías. Y viceversa, JAVA se puede integrar en JESS. Ahora lo que se va a ver es cómo se puede integrar JESS en un agente inteligente.

JESS se incluye dentro de un comportamiento de un agente, como la siguiente estructura:
//import jade.core.Agent;
import jade.core.behaviours.*;
import jess.*;
public class pruebaJess extends Agent
{
   protected void setup()
   {
      addBehaviour(new JessBehaviour());
   }
   class JessBehaviour extends TipoComportamiento
   {
      //AQUÍ SE INCLUYE EL CÓDIGO PARA USAR JESS
   }
}//

LA CLASE RETE

Una de las clases más importantes que tiene JAVA para comunicarse con JESS es jess.Rete. Con ella se genera el motor de reglas y cada objeto de esta clase tiene su propia memoria de trabajo. Para comunicarse con JESS se debe crear una instancia de esta clase:
//class JessBehaviour extends OneShotBehaviour
{
   public void action()
   {
       // Define el motor de JESS
       Rete jess = new Rete();
   }
}//

Muchas funciones de JESS tienen su equivalente en la clase Rete:
  • batch(String): equivalente a (batch archivo), carga un archivo .clp//.
  • run(), run(int): equivalentes a (run [integer]), ejecuta el motor de inferencias de manera que dispara todas las reglas aplicables hasta que no queden más, en cuyo momento el hilo queda boqueado, por lo tanto, el agente. Se puede poner el número máximo de reglas a ejecutar antes de pararlo.
  • reset(): equivale a (reset).
  • clear(): equivale a (clear), borra reglas, deffacts, defglobals, templates, facts… menos funciones.
  • assertFact(Fact): equivale a (assert (hecho)), añade un hecho que debe estar definido de tipo Fact.
  • assertString(“hecho”): a (assert (hecho)), añade un hecho que se pasa como String.
  • retract(Fact), retract(int): equivalen a (retract hecho), eliminan un hecho.
  • halt(): equivale a (halt), detiene la ejecución de las reglas.

Las llamadas a JESS suelen exigir en tiempo de compilación que se trate la excepción jess.JessException:
try
{
   jess.reset();
   jess.batch("viviendaInteligente/viviendaInteligente.clp");
} catch (JessException ex) {
   System.err.println(ex);
}
Hay un método muy práctico: eval(String), cuyo parámetro es el código JESS que se quiere ejecutar. Aunque se puede trabajar con este método como si no devolviera nada, devuelve los resultados de tipo jess.Value:
try
{
   jess.batch("factorial.clp");
   Value v = jess.eval("(fact 5)");
   System.out.println(v.intValue(jess.getGlobalContext()));
} catch (JessException ex) {
   System.err.println(ex);
}
 


arriba.png7.3.4 Ejemplo práctico (viviendaInteligente.rar)


DESCRIPCIÓN DEL PROBLEMA

Este ejemplo es una pequeña simulación de una vivienda inteligente, donde se pretende controlar:

  • Que la temperatura sea de 20 grados.
  • Que cuando la vivienda esté vacía la puerta de la entrada esté cerrada con llave.
  • Que cuando la vivienda esté vacía la alarma esté conectada.
  • Que cuando la vivienda esté vacía las luces estén apagadas.
  • Que cuando la alarma se active se haga una llamada a la policía.
  • Que cuando la nevera esté apagada tenga la puerta abierta y que cuando esté encendida la tenga cerrada.
  • Que cuando el horno esté funcionando tenga la puerta cerrada.

SOLUCIÓN DEL PROBLEMA

Para resolver el problema, se ha decidido realizar un programa con dos agentes inteligentes, uno (Sensores) que se encargue de leer los sensores de la casa y le pase la información a otro agente (Controlador) que tendrá integrado en un comportamiento un programa JESS. Este programa comprobará la información de los sensores y dará las órdenes oportunas para que la vivienda “funcione correctamente”.

controlador-sensores.JPG


AGENTE SENSORES

Este agente se encarga de leer la información que reciben los sensores de la casa: horno, nevera, temperatura y la luz, alarma y puerta según haya o no gente en la vivienda. Para ello tiene un comportamiento cíclico, que se está ejecutando constantemente.

La información se le pasa al agente Controlador mediante un mensaje ACL. Tal que así:
ACLMessage msg=new ACLMessage(ACLMessage.INFORM);
msg.addReceiver(new AID("controlador",AID.ISLOCALNAME));
msg.setContent(hecho);
myAgent.send(msg);

AGENTE CONTROLADOR

Este agente se encarga de comunicarse con el programa JESS cada vez que un sensor cambia de estado, por lo que va a tener siempre el valor actual de todos los sensores.Comprueba constantemente la información que recibe de Sensores. Si se refiere a la temperatura llama a la función correspondiente. Si no, comprueba a qué hecho se refiere y cual es el nuevo estado, si es distinto al actual, añade el nuevo hecho y borra el actual. Finalmente, después de cada lectura, llama al método run() para que JESS compruebe los nuevos hechos y ejecute la regla que corresponda si es necesario.


PROGRAMA JESS

El programa JESS está en el archivo viviendaInteligente.clp. Como es un simulador, indica los cambios por pantalla.

Cuando el agente Controlador carga el programa, define una variable global ?*temperatura* que representa la temperatura de la casa y se modificará cada vez que se llame a las funciones bajando() o subiendo(). Cuando el agente Sensores indica que la temperatura está bajando, se llama a la función bajando(), que aumenta un grado la temperatura si está por debajo de los 20 grados, subiendo() funciona a la inversa.

Reglas:

  • puertaCerrada: si la vivienda está vacia y la puerta está abierta entonces cierra la puerta con llave.
  • alarmaConectada: conecta la alarma si está desconectada y la vivienda está vacía.
  • apagarLuces: apaga las luces de la vivienda si está vacía y si las luces están encendidas.
  • llamarPolicia: llama a la policía si la alarma se activa.
  • neveraApagada: enciende la nevera si está apagada y con la puerta cerrada.
  • neveraEncendida: si la nevera está funcionando cierra la puerta de la misma.
  • hornoEncendido: cierra la puerta del horno si éste está funcionando.

arriba.png


7.4 Ejercicio


EJERCICIO 2010/2011 Grupo MIÑO

Habrá 4 archivos:
  • index2: Será un formulario para el enviar Dirección, Asunto y Conteido al servlet.
  • ServletValidar: Recibe los campos anteriores, crea el objeto de tipo Mensaje y lo envia a MiAgenteGateWay.
  • MiAgenteGateWay: Recibe el Mensaje, crea un mensaje ACL y se lo envia a receptor.
  • Receptor: Tras recibir los datos, se encarga de mostrarlos por consola.
  • Mensaje: Tipo de dato.

DiagramaSMA.png

















Los ficheros se deberán enviar comprimidos (.rar o .zip) a la direccion grupominho1011@gmail.com indicando vuestro nombre y grupo.




NOTA: parte de los ejemplos de este wiki han sido sacados y modificados de la documentación de JADE y de un TAD sobre la integración de JESS y JADE de la Escuela Superior de Ingeniería Informática de Ourense.