Java AppServer-01: Intro Application Server

Septiembre 15th, 2009 por Enrique Leave a reply »

Ahora que tenemos un servicio RPC podemos usarlo como base para implementar un servidor de aplicaciones, pero solamente un servicio RPC no alcanza. Por esto, vamos a implementar estos módulos/servicios:

  • Seguridad: autorización, autenticación y auditoria

  • Pool de conexiones a la base de datos

  • Servicio de mensajería asíncrona

Y, además de tener una API para agregar servicios, el servidor va a proveer una API para agregar módulos del usuario. Ahora el diagrama de componentes del servidor:

Diagrama de componentes

Diagrama de componentes

Los componentes de la capa superior utilizan funcionalidades de los componentes de la capa inferior. Ahora vamos a explorar cada uno de los componentes.

Security realms manager

Esto es obligatorio en cualquier AppServer. En el Security Realms Manager se instalan los security realms. ¿Qué es un security realm? Conceptualmente es un componentes que controla el acceso al los servicios. Desde el punto de vista técnico, es la implementación de la interfaz:

public interface SecurityRealm {
    /**
     * The login method.
     * @param credentials The credentials to validate
     * @throws LoginException If an exeption ocurrs during login
     */
    void login(Credentials credentials) throws LoginException;

    /**
     * The logout method.
     * @param credentials The credentials
     */
    void logout(Credentials credentials);

    /**
     * This method returns true if and only if the service's method can be
     * executed with the given credentials.
     *
     * @param credentials the credentials of the executing user
     * @param serviceName the service name
     * @param methodName the method name to execute
     * @param params the paramenters to pass to the method
     * @throws NotExecutedException signals that the execution is not allowed for the given credentials, serviceName, methodName and params
     */
    void executionAllowed(Credentials credentials, String serviceName, String methodName, Object... params) throws NotExecutedException;
}

Son solamente tres métodos: login, logout y isExecutionAllowed. Los dos primeros refieren al concepto de autenticación y el tercero refiere al concepto de autorización, pero también se puede asociar a auditoría ya que siempre se ejecuta antes de realizar la invocación al servicio.

El security realms manager utiliza el interceptor que aparece en Java RPC-07: en el método onPreExecution() se llama al método executionAllowed() del security realm y continúa la ejecución si este no da la excepción NotExecutedException. Por seguridad, tampoco ejecuta si ocurre cualquier otra excepción (o error) en el executionAllowed() y así evita que un bug quiebre el sistema de seguridad.

Entonces poniendo código arbitrario en método executionAllowed() se puede autorizar o no la ejecución de un método de un servicio con determinados parámetros.

El security realms manager maneja una colección de security realms. Se ejecutan todos y solamente se da por autorizada la llamada si todos autorizaron. El servidor tiene implementado un security realm abstracto que se basa en nombre de usuario y contraseña y otro security realm para hacer auditoría (logging).

public abstract class AbstractUserPasswordSecurityRealm extends SecurityRealmAdapter {

    public AbstractUserPasswordSecurityRealm() {
    }

    public void login(Credentials c) throws LoginException {
        UserPasswordCredentials cred = (UserPasswordCredentials)c;
        if (cred != null) {
            String user = cred.getUser();
            String pass = cred.getPassword();
            validate(user, pass);
        } else {
            throw new LoginException("null credentials");
        }
    }

    public void executionAllowed(Credentials credentials, String serviceName, String methodName, Object... params) throws NotExecutedException {
        if (credentials == null) {
            throw new NotExecutedException("not logged in");
        }
    }

    public abstract void validate(String user, String pass) throws LoginException;
}

Module manager

Como vimos, el servidor es extensible. ¿Pero cómo? Mediante módulos. Un módulo no es más que un bean que tiene un nombre y dos métodos para el manejo del ciclo de vida: startup() y shutdown(). Luego, el servidor tiene un método para obtener el módulo por su nombre. Como es tan simple la interfaz, es fácil adaptar cualquier servicio para incorporarlo al servidor. Por ejemplo, el servicio de mensajería asíncrona se implementó por separado y se creó un módulo para adaptarlo a este servidor de aplicaciones. Idem con el pool de conexiones a la base de datos. La interfaz:

public interface Module {
    void setName(String name);
    String getName();

    void startup() throws Exception;
    void shutdown();
}

Para obtener un módulo desde un servicio, se lo pedimos al ServerContext:

ServerContext.getModule(moduleName);

La clase ServerContext nuclea un conjunto de métodos estáticos que dan acceso a diferentes partes del servidor de aplicaciones. Los que más se desatacan son getModule() y getServerConfig(). El primero ya lo vimos. El segundo devuelve un Mapa con propiedades que se cargan de un archivo de configuración. Ya veremos la configuración en una sección dedicada a esta.

Services Loader

Este es el componente encargado de leer de un archivo de configuración y crear los servicios en el RPC. Está implementado como módulo así se puede reemplazar fácilmente por otro y se acopla al servidor. Básicamente lee de un archivo de configuración la descripción de los servicios con sus parámetros y los agrega al servidor.

En el siguiente artículo voy a describir el pool de conexiones a la base de datos y el servicio de mensajería. También voy a describir los archivos de configuración.

Hasta el próximo.

  • Blogger Post
  • Digg
  • Reddit
  • Google Reader
  • Share/Bookmark
Advertisement

Deja un comentario

Spam protection by WP Captcha-Free