Documentazione Contatti      
Documentazione > Tutorial > Resin Application Server
Hide
Best Practices
EJB
Frameworks
Howto
J2EE
J2ME and Wireless
J2SE
JSP e Servlet
Java Application Server
Java IDE/Tools
Java Media
Java Security
Java Sys Admin
Java e XML
Java e SQL
OpenSource Java
Patterns
Repository
Tesi
UML
Web Services
Slide
White Paper di jws.it
project management
Eventi
Groovy



VMware ha comprato SpringSource


Un giorno le macchine riusciranno...
a risolvere tutti i problemi, ma mai nessuna di esse potra' porne uno. Einstein


[GRASP] Pattern Controller



  Visualizza Commenti (1) Aggiungi Commento    
 
Resin Application Server
By Alfonso Iannotta
24 gennaio 2006
Valutazione Acquisita: 110

  Resin Application Server
Program Installazione e configurazione di Resin
Program Deploy di web application
Program Virtual Hosting
Program Deploy di Enterprise Application
Program Configurazione di un DataSource
Program Configurazine di JMS
Program Sicurezza
Program Performance
Program Clustering
Program Conclusioni e ringraziamenti

Resin è un application server che supporta tutte le tecnologie J2EE integrando caratteristiche di Web server e offrendo funzionalità avanzate per sistemi Enterprise. Rispetto ai prodotti dedicati alle imprese come Weblogic e Websphere (tanto per citare i più importanti) oppure Jboss (se vogliamo andare sul software libero), Resin è un application server  Open source leggero e di semplice utilizzo quindi molto adatto ad ambienti di sviluppo; nonostante questo si è dimostrato un prodotto completo e affidabile adatto anche agli ambienti di produzione.

Come abbiamo detto Resin supporta tutte le tecnologie della piattaforma J2EE, e quindi Servlet e JSP, EJB, JDBC, JMS, e Web Services. Inoltre gestisce Virtual host , pagine PHP, CGI in genere, e supporta OpenSSL.

Per i sistemi di impresa che richiedono caratteristiche di robustezza, affidabilità, e alte performance Resin fornisce sistemi di clustering e load balancing, oltre ad un insieme di librerie JNI per ottimizzare la gestione delle socket e l’accesso al file system. Resin supporta inoltre una serie di altre feature (che non approfondiremo in questo articolo) come: JSP EL (Expression Language) un linguaggio con sintassi semplificata per l'accesso ad oggetti e per l'utilizzo delle loro proprietà a run-time dall'interno di pagine JSP; JCA (Java Connection Architecture); Amber un’implementazione di Resin della persistenza degli EJB 3.0; i protocolli Hessian e Burlap, per la connessione con i web-services; XTP (XML Template Pages) che permette la creazione di pagine web tramite XML.



Installazione e configurazione di Resin top

 
L’istallazione di resin è quanto di più semplice si possa pensare; dal sito della Caucho Tecnology (www.caucho.com) facciamo il download del pacchetto, facendo attenzione a scaricare la versione professional del server. Ora scompattiamo il file compresso in una directory a nostra scelta, chiameremo questa directory RESIN_HOME. Installiamo la JDK (alcune funzionalità dell’ultima versione di Resin necessitano della JDK 1.5) e settiamo la variabile d’ambiente JAVA_HOME.

Se siamo su un sistema Unix dobbiamo eseguire la classica sequenza di comandi di istallazione:

  1. ./configure;
  2. make;
  3. make install

L’ application server Resin è scritto essenzialmente in Java; i moduli che vengono compilati nella sequenza di istallazione sono per il supporto OpenSSL e per la gestione avanzata delle socket tramite librerie JNI.

A questo punto siamo pronti per far partire il nostro server Resin; se siamo su Unix utilizziamo il comando httpd.sh che si trova nella directory RESIN_HOME/bin per lanciare il nostro server Resin in foreground, oppure https.sh start|stop|restart per lanciare, fermare,o restartare il nostro server in background. Se siamo su piattaforma Windows basta lanciare l’eseguibile httpd.exe che si trova nella RESIN_HOME. In entrambi i casi gli autori di Resin hanno scelto di wrappare il processo java in un eseguibile; su windows httpd.exe genera una piccola console con cui è possibile gestire lo stato del server Resin (start,stop) o uscire dal programma (quit):

 

Fig 1 - console  di gestione server

Su piattaforma Unix questo eseguibile è uno script PERL wrapper.pl che oltre a gestire lo stato del server si occupa di restartare Resin nel caso in cui cada il processo java.

Ora apriamo il browser all’indirizzo http://localhost:8080 e apparirà la pagina di default di Resin:

 

Fig 2 - pagina di default di Resin

Bene ora impariamo come configurare un server Resin; ci sono alcuni punti da tenere presenti nella filosofia di gestione di un server Resin

  • C’è un solo file xml di configurazione per il server, il resin.conf
  • I file di configurazione delle web application sono il WEB-INF/web.xml e WEB-INF/resin-web.xml; il primo contiene le configurazioni standard della web application, il secondo le configurazioni specifiche di Resin. 
  • Ogni cambiamento nel file di configurazione viene rilevato automaticamente e causa il restart del server
  • Ogni cambiamento nel file di configurazione di una web application viene rilevato automaticamente e causa il restart della web application
  • Un nuova web application viene deployata automaticamente aggiungendo un file .war nella directory webapps
  • Un nuovo virtual host viene aggiunto automaticamente creando una sottodirectory nella directory host
  • I path vengono interpretati come assoluti se iniziano con “/” altrimenti relativi alla RESIN_HOME

Come vedremo nel seguito dell’articolo è possibile anche aggiungere una nuova web application o un virtual host modificando appropriatamente il file resin.conf. Le direttive specifiche di Resin contenute nel resin-web.xml possono essere inserite anche nel web.xml, anche se questo rende questo file non standard per eventuali deploy su altri application server.

Resin può essere usato come server stand alone con funzioni di web server e application server o in alternativa si può usare un web server come Apache o IIS come front end per servire contenuti statici e Resin come application server di back end per l’elaborazione di contenuti dinamici. L’integrazione con Apache e IIS viene realizzata tramite un modulo plugin (mod_coucho per Apache o isapi_srun.dll per IIS) che ha il compito di selezionare le URL da passare all’application server, inoltrare le richieste e riprendere le risposte dal server Resin.



Deploy di web application top

 Nel file resin.conf è presente un insieme di entry che definisce il deployment delle applicazioni su Resin; la directory di default per il deploy delle applicazioni è RESIN_HOME/webapps.Il context path di default delle applicazioni è RESIN_HOME/webapps/ROOT per le JSP, mentre è RESIN_HOME/webapps/WEB-INF/classes per le servlet e le calssi java.

L’istallazione di una web application su un server Resin può essere fatta in diversi modi:

  • Deploy di un file WAR
  • Creazione di una directory nella cartella webapps
  • Configurazione attraverso il file resin.conf

 Se possediamo il file .war della nostra applicazione basterà copiarlo in questa directory per farlo deployare automaticamente in una directory con lo stesso nome del file war; proviamo ad esempio a deployare il file moltiplicazione.war (http://www.javaportal.it../../../../../JIP/Attachment/20050922/moltiplicazione.war.zip) se Resin è attivo sulla console possiamo vedere il deploy a runtime dell’applicazione al termine della quale possiamo anche vedere la URL con la quale è possibile visualizzare l’applicazione.

 
Fig 3 -  deploy a runtime dell’applicazione sulla console

Ora richiamiamo la webapp tramite il nostro browser alla url http://localhost:8080/moltiplicazione/ServletInput.html e proviamone l’efficienza.

Il secondo modo, e il più semplice, per deployare una nuova web application su Resin è quello di creare una sottodirectory in RESIN_HOME/webapps; se ad esempio creiamo la directory prova ;Resin interpreta la nuova directory come una web application vuota e prepara l’ambiente per inserire i componenti della webapp, quindi inserisce nella nuova directory la seguente porzione di file system:

 
La context root della nuova web application è RESIN_HOME/webapps/prova mentre le classi e le servlet dovranno essere deployate sotto RESIN_HOME/webapps/prova/WEB-INF/classes. Ora inseriamo nella cartella prova una qualsiasi JSP (diciamo index.jsp) e testiamo la aprendo il browser alla url http://localhost:8080/prova/index.jsp.

 Per i deploy automatici vengono applicati i parametri di default, ma se necessitiamo di una web application con dei settaggi particolari allora dobbiamo configurarla nel file resin.conf . Questo è il terzo modo per deployare una web application su Resin; se ad esempio nel file resin.conf inserisco al seguente entry:

  <host id="" root-directory=".">

      …

      <web-app id="/molti">

          <document-directory>apps</document-directory>

          <archive-path>webapps/moltiplicazione.war</archive-path>

      </web-app>

  </host>

In questo caso abbiamo creato una web application “molti” che sfrutta lo stesso war deployato in precedenza automaticamente sotto la webapps. Il war verrà deployato nela directory RESIN_HOME/apps; attenzione prima del deploy verrà cancellato tutto il contenuto di questa directory, quindi assicuratevi che non contenga file importanti; se tale directory non esiste verrà creata. Se infine non viene specificata la document-directory il war viene deployato in una directory della RESIN_HOME con lo stesso nome della web application, nel nostro caso in RESIN_HOME/molti



Virtual Hosting top

Resin permette di gestire i Virtual Host. Per chi non lo sapesse il virtual hosting è la possibilità di avere diversi domini erogati dallo stesso server. Ad esempio è possibile avere due domini www.miodominiouno.it e www.miodominiodue.it, completamente indipendenti, erogati dallo stesso server Resin. Esistono due modi per configurare un virtual host su Resin:

1. Dinamic Virtual Host
2. Standalone Virtual Host

 Per quanto riguarda il Dinamic Virtual Host nel file resin.conf  viene configurata la seguente direttiva:

<host-deploy path="hosts">

Con questa direttiva specifichiamo al server Resin che nella directory “hosts” contenuta nella RESIN_HOME metteremo tutti i nostri virtual host; da notare che la directory “hosts” non esiste di default nella RESIN_HOME, è quindi necessario crearla a mano. Il modo più semplice per creare un virtual host con Resin è quello di creare un sotto-directory in RESIN_HOME/hosts; Resin a runtime, oppure al riavvio, interpreta il nome della directory creata come il nome di un virtual host, e addirittura crea la struttura delle directory necessaria per deployare le applicazioni sotto il nuovo virtual host; se ad esempio creiamo la directory “miohost” dopo qualche secondo automaticamente Resin creerà la seguente porzione di filesystem:

La directory webapps, generata automaticamente da Resin, è delegata a contenere le web application che verranno invocate tramite il nome del nostro virtual host. Per il deploy di web application nel nostro virtual host valgono le stesse regole descritte precedentemente solo che in questo caso la directory di default sarà RESIN_HOME/hosts/miohost. Quindi prendiamo il nostro moltiplicazione.war utilizzato in precedenza e copiamolo nella directory

RESIN_HOME/hosts/miohost/webapps per farlo deployare; dopodichè inseriamo nel file hosts della nostra macchina la seguente riga:

 127.0.0.1 miohost

A questo punto apriamo il nosro browser alla url http://miohost:8080/moltiplicazione/ServletInput.html per testare il funzionamento del nuovo virtual host.

Da notare che non viene creata automaticamente la cartella ROOT; nonostante questo la context path di default per il nuovo virtual host è RESIN_HOME/hosts/miohost/ROOT. Per cui se vogliamo che una qualsiasi JSP, diciamo index.jsp, sia raggiungibile attraverso la url http://miohost:8080/index.jsp, dobbiamo creare a mano la cartella RESIN_HOME/hosts/miohost/ROOT e inserirvi la index.jsp.

 
La configurazione Standalone di un Virtual Host viene fatta inserendo i nel resin.conf le seguenti direttive:

<host id='miohost'>
   <root-directory>nuovihost/miohost</root-directory>
</host>
Come nel caso precedente Resin crea , nella directroy specificata da root-directory,  la porzione di file system necessaria per deployare le applicazioni sotto il nostro virtual host; se la root-directory non esiste allora viene creata.  Il resto della gestione è uguale al Dinamic Virtual Host.


Deploy di Enterprise Application top

 Diversamente dagli altri Application Server che istanziano l’EJB container di default, Resin crea il container degli EJB solo se necessario. Quindi quando una web application utilizza degli EJB deve configurare all’interno del resin-web.xml l’ejb-server specificando dove si trova il descrittore degli EJB ejb-jar.xml e il nome JNDI necessario per reperire il Context:

<ejb-server jndi-name="java:comp/env/ejb">
  <ejb-descriptor>META-INF/ejb-jar.xml</ejb-descriptor>
</ejb-server>


Nella tabella seguente sono contenute le descrizioni di tutti i parametri di configurazione dell’ejb-server:

 

Fig 4 - i parametri di configurazione dell’ejb-server

Creiamo ora un EJB da deployare nel nostro container; il nostro EJB avrà un metodo che restituisce il numero totale di volete che l’EJB è stato invocato. Abbiamo quindi bisogno dei seguenti elementi:

•    Remote Interface
•    Home interface
•    Bean Implementation
•    Deployment descriptor

Nella RESIN_HOME/webapps creiamo una nuova directory “counter”; come spiegato precedentemente Resin crea automaticamente l’ambiente per il deploy della web application. Sotto counter/WEB-INF/classes inseriamo la cartella ktech che conterrà le classi del nostro EJB e infine creiamo la cartella counter/META-INF dove inseriremo il nostro deployment descriptor.
Innanzitutto scriviamo la Bean Implementation nel file CounterBean.java:

package ktech;

import javax.ejb.*;
import java.util.*;

public class CounterBean implements SessionBean {
  int count;

    private SessionContext ctx;        
    public CounterBean() {}
    public void setSessionContext(SessionContext c) {
        ctx=c;
    }

    public void ejbCreate() {}    
    public void ejbRemove() {}   
    public void ejbPassivate() {}
    public void ejbActivate() {}

  public int hit()
  {
    return ++count;
  }
}


Quindi la Home Interface in CounterLocalHome.java :

package ktech;
import javax.ejb.*;
public interface CounterLocalHome extends EJBLocalHome {
  CounterLocal create() throws CreateException;
}

e la Remote Interface in CounterLocal.java :

package ktech;
import javax.ejb.*;
public interface CounterLocal extends EJBLocalObject {
  int hit();
}


Ora per completare il deploy dobbiamo scrivere il Deploy Descriptor ejb-jar.xml :

<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/j2ee/dtds/ejb-jar_2_0.dtd">
<ejb-jar>
<enterprise-beans>
  <session>
    <ejb-name>counter</ejb-name>
    <local-home>ktech.CounterLocalHome</local-home>
    <local>ktech.CounterLocal</local>
    <ejb-class>ktech.CounterBean</ejb-class>
    <session-type>Stateful</session-type>
    <transaction-type>Bean</transaction-type>
  </session>
</enterprise-beans>  
</ejb-jar>


All’avvio di Resin possiamo leggere nella console le fasi di compilazione dell’EJB. Durante la compilazione viene creata dall’application server una directory work/ejb/_ejb/counter sotto counter/WEB-INF all’interno della quale viene deployato l’EJB. Ora non ci rimane che invocare l’EJB tramite una jsp che chiameremo counter.jsp:

<%@ page language="java" import="ktech.*, javax.naming.* " %>
<%

CounterLocalHome convHome;
CounterLocal conv;

HttpSession hs = request.getSession();
conv = (CounterLocal) hs.getAttribute("home");
if ( conv == null){
   try {
    Context ejb = (Context) new InitialContext().lookup("java:comp/env/ejb");
    convHome = (CounterLocalHome) ejb.lookup("counter");
    } catch (NamingException e) {
        throw new ServletException("java:comp/env/ejb",e);
    }
 conv = convHome.create();
 hs.setAttribute("home",conv);
 }
%> EJB chiamato : <%= conv.hit() %> volte <br/>
<a href="http://localhost:8080/counter/counter.jsp">Richiama</a>


Ora apriamo il browser alla URL http://localhost:8080/counter/counter.jsp  e vediamo come cliccando sul link “Richiama” si incrementano le chiamate all’ejb:

 
Fig 5 - Le chiamate all' EJB si incrementano 

Resin supporta anche una modalità deploy automatico degli EJB; invece di utilizzare l’ejb-jar.xml come unico deploy descriptor viene utilizzato un file descriptor differente per ogni EJB con estensione *.ejb. Configurando il nostro ejb-server nel seguente modo:

<ejb-server jndi-name="java:comp/env/ejb" config-directory="WEB-INF"/>

diciamo all’application server di leggere tutti i file *.ejb contenuti nella directory WEB-INF ed effettuare il deploy. Il contenuto dei file *.ejb è identico a quello del file ejb-jar.xml tranne che per il fatto che viene descritto un unico EJB. Nel caso dell’esempio precendente scriveremo un file CounterBean.ejb di questo tipo:

<ejb-jar>
<enterprise-beans>
  <session>
    <ejb-name>counter</ejb-name>
    <local-home>ktech.CounterLocalHome</local-home>
    <local>ktech.CounterLocal</local>
    <ejb-class>ktech.CounterBean</ejb-class>
    <session-type>Stateful</session-type>
    <transaction-type>Bean</transaction-type>
  </session>
</enterprise-beans> 
</ejb-jar>



Configurazione di un DataSource top

 La configurazione di un DataSource con Resin è molto semplice e può essere fatta sia a livello di server, e quindi all’interno del resin.conf, sia a livello di web application, e quindi nel resin-web.xml. Una tipica configurazione di un datasource per il DB MySQL è la seguente:

<database>
  <jndi-name>jdbc/mysql</jndi-name>
  <driver>
    <type>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</type>
    <url>jdbc:mysql://localhost:3306/dbname</url>
    <user>username</user>
    <password>password</password>
  </driver>
  ...
</database>


Nella configurazione dobbiamo specificare il nome JNDI con cui verrà reperito il DataSource, la classe che implementa il DataSource per lo specifico database (nell’esempio specifico viene utilizzata una versione avanzata dei driver per MySQL che fa uso dei Connector-J), la URL del database dove dbname è il nome dello schema che vogliamo utilizzare, user e password per lo schema precedentemente specificato. Un semplice esempio di codice per accedere al database è il seguente:

……
int contaRighe() throws ServletException
  {
  String DATASOURCE_NAME = "jdbc/mysql";
  int numeroRighe = -1;
  DataSource pool;
    try {
      Context env = (Context) new InitialContext().lookup("java:comp/env");
      pool = (DataSource) env.lookup(DATASOURCE_NAME);
      if (pool == null)
        throw new ServletException("`" + DATASOURCE_NAME + "' is an unknown DataSource");
    } catch (NamingException e) {
      throw new ServletException(e);
    }
    Connection conn = null;
    try {
      conn =pool.getConnection();
      Statement stmt = conn.createStatement();
      ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM `nomeTabella`");
      while (rs.next()) {
      numeroRighe = rs.getInt(1);
      }
      rs.close();
      stmt.close();
    } catch (SQLException e) {
      throw new ServletException(e);
    } finally {
      try {
        if (conn != null)
          conn.close();
      } catch (SQLException e) {
      }
    }
    return numeroRighe;
  }
……



In questo esempio abbiamo scritto un metodo che conta le righe di nomeTabella;
Di seguito riportiamo una tabella con la lista completa dei parametri di configurazione di un DataSource:

 

 Fig 6 -parametri di configurazione di un DataSource

Per una configurazione avanzata del DataSource possiamo impostare una serie di parametri del pool di connessione (pooling parameter), oppure dei parametri per verificare l’affidabilità della connessione con il database (reliability parameter) oppure utilizzare un sistema di caching degli ultimi statement utilizzati impostando il tag prepared-statement-cache-size ad un valore diverso da zero.



Configurazine di JMS top

 Resin supporta l’utilizzo delle code JMS sia di tipo Point-to-Point (Queue) che Publish/Subscribe (Topics). In particolare vengono forniti due possibili implementazioni:

1.    Non Persistente in memoria
2.    Persistente su database

Nella prima soluzione le code JMS sono residenti in memoria; a fronte di una minore affidabilità le code JMS non persistenti forniscono un servizio più performante. Le code JMS persistenti invece utilizzano un database per lo storage dei messaggi, mantengono quindi i messaggi in coda anche in caso di interruzione del servizio.
Vediamo ora come configurare una coda JMS di tipo queue non persistente; nel notro resin-web.xml inseriremo le seguenti righe:

<resource jndi-name="jms/my-queue" type="com.caucho.jms.memory.MemoryQueue">
  <init>
    <queue-name>my-queue</queue-name>
  </init>
</resource>


oppure se vogliamo configurare un topics:

<resource jndi-name="jms/my-topic" type="com.caucho.jms.memory.MemoryTopic">
  <init>
    <topic-name>my-topic</topic-name>
  </init>
</resource>


Se invece vogliamo configurare una queue di tipo persistente dobbiamo prima definire il DataSurce dove verranno memorizzati i messaggi; supponiamo di utilizzare lo stesso DataSource definito nel paragrafo precedente:

<database>
  <jndi-name>jdbc/mysql</jndi-name>
  <driver>
    <type>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</type>
    <url>jdbc:mysql://localhost:3306/dbname</url>
    <user>username</user>
    <password>password</password>
  </driver>
</database>


 Dopodichè configureremo la queue persistente specificando il DataSource utilizzato per lo storage dei messaggi, in questo modo:

<resource jndi-name="jms/my-queue" type="com.caucho.jms.jdbc.JdbcQueue">
  <init>
    <queue-name>my-queue</queue-name>
    <data-source>jdbc/mysql</data-source>
  </init>
</resource>


Se invece vogliamo configurare un topic persistente:

<resource jndi-name="jms/my-topic" type="com.caucho.jms.jdbc.JdbcTopic">
  <init>
    <topic-name>my-topic</topic-name>
    <data-source>jdbc/mysql</data-source>
  </init>
</resource>


Al momento dell’avvio Resin crea automaticamente sul database specificato tre tabelle necessarie per la gestione della coda JMS:

•    resin_jms_consumer – Contiene la lista degli consumer registrati alle code JMS configurate
•    resin_jms_destination – Contiene la lista delle code JMS configurate
•    resin_jms_message – Contiene i messaggi inviati alle code JMS configurate

La gestione delle tabelle è totalmente a carico dell’application server Resin e quindi completamente trasparente.
Vediamo ora come sfruttare le code JMS appena create; come è noto i client che scrivono e leggono la coda JMS utilizzano una ConnectionFactory specifica per ogni tipo di Application server che viene reperita tramite JNDI dall’application server stesso. Quindi la prima cosa da fare è definire la ConnectionFactory nella nostra applicazione; quindi nel resin-web.xml inseriremo la seguente direttiva:

<resource jndi-name="jms/simple-factory" type="com.caucho.jms.ConnectionFactoryImpl"/>

Ora scriviamo una semplice jsp che invia un messaggio alla coda JMS:

<%@ page language="java" import="ktech.*, javax.naming.*, javax.jms.* " %>
<%

Context context = null;
Connection conn = null;
Session sess = null;
javax.jms.Queue queue = null;
MessageProducer sender = null;
TextMessage message = null;
String testo = "testo di prova";
String esito = null;

  try {
      context = new InitialContext();
     

ConnectionFactory

factory = (ConnectionFactory)context.lookup("java:comp/env/jms/simple-factory");
      conn = factory.createConnection();
      sess = conn.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
      queue = (javax.jms.Queue)context.lookup("java:comp/env/jms/my-queue");
      sender = sess.createProducer(queue);
      message = sess.createTextMessage();
      message.setText(testo);
      sender.send(queue, message);
      esito = "Riuscito";
  } catch (NamingException e) {
    e.printStackTrace();
    esito = "Fallito";
  }
 
%> Esito invio messaggio<%= esito %><br/>


Questa jsp non fa altro che inviare una stringa “testo di prova” alla coda JMS. A questo punto se stiamo utilizzando una coda persistente possiamo vedere nella tabella resin_jms_message il messaggio che è stato messo nella coda. Per completare il giro dobbiamo creare un consumer che legga i messaggi inviati alla coda JMS; scriviamo quindi un Message Driver Bean (MDB) che legge la coda e logga sulla console il contenuto dei messaggi:

package ktech;

import javax.ejb.*;
import javax.jms.*;

public class SimpleMessageBean implements MessageDrivenBean, MessageListener {

  public void ejbCreate() throws EJBException {}
  public void setMessageDrivenContext(MessageDrivenContext cxt) throws EJBException {}
  public void ejbRemove() throws EJBException {}

  public void onMessage(Message msg)
  {
    String text = null;

    if (msg instanceof TextMessage) {
      try {
        text = ((TextMessage) msg).getText();
      } catch (Exception ex) {
        ex.printStackTrace();
      }
    }
    else {
      text = msg.toString();
    }
    System.out.println("Messaggio: " + text);
  }
}


Configuriamo sul resin-web.xml l’ejb-server, necessario per deployare l’MDB, specificando la ConnectionFactory che deve utilizzare l’MDB stesso:

<ejb-server config-directory="WEB-INF">
   <jms-connection-factory>jms/simple-factory</jms-connection-factory>
</ejb-server>

Scriviamo infine il descrittore dell’MDB, il file SimpleMessageBean.ejb :

  <message-driven>
    <ejb-name>SimpleMessageBean</ejb-name>
    <ejb-class>ktech.SimpleMessageBean</ejb-class>
    <destination>jms/my-queue</destination>
  </message-driven>


Quando l’MBD viene deployato si collega alla coda JMS, legge i messaggi inviati dalla jsp e li stampa sulla console di Resin.

 



Sicurezza top

 
Resin fornisce una serie di API per la gestione della sicurezza che le applicazioni possono utilizzare per proteggere le risorse senza implementare librerie ad-hoc. L’autenticazione si basa principalmente su 3 elementi: l’authenticator che definisce il tipo di autenticazione da utilizzare e le utenze, il login-config che definisce il tipo di login con cui accedere ai contenuti protetti, il security-constraint che definiscono le politiche di sicurezza.

Resin offre due tipi di authenticator:

•    XmlAuthenticator
•    JdbcAuthenticator

L’XmlAuthenticator è il più semplice da utilizzare, premette di configurare user e password direttamente nel file di configurazione resin.conf o resin-web.xml della nostra applicazione:

  <authenticator type="com.caucho.server.security.XmlAuthenticator">
    <init>
      <user>pippo:pluto:user</user>
      <password-digest>none</password-digest>
    </init>
  </authenticator>

In questa configurazione abbiamo definito un utente “pippo” con password “pluto” e ruolo “user”.
Per utilizzare il JdbcAuthenticator dobbiamo innanzitutto definire un DataSource; supponiamo di utilizzare il solito DataSource definito nei paragrafi precedenti. Dopodiche dobbiamo creare manualmente una tabella che contenga le utenze comprensive di userid, password e ruolo. Infine configuriamo l’JdbcAuthenticator specificando il DataSource e le  query necessarie ad estrarre password e ruolo:

  <authenticator type='com.caucho.server.security.JdbcAuthenticator'>
    <init>
      <data-source>jdbc/test_mysql</data-source>
      <password-digest>none</password-digest>
      <password-query>
        SELECT password FROM LOGIN WHERE utente=?
      </password-query>
      <role-query>
        SELECT role FROM LOGIN WHERE utente=?
      </role-query>
    </init>
  </authenticator>

Ovviamente nella tabella “LOGIN” dovremo aggiungere un record con le credenziali dell’utente.
Ora configuriamo il tipo di login sempre nel resin-web.xml :

  <login-config auth-method='basic'/>

Per il nostro esempio abbiamo scelto il metodo di autenticazione più seplice, pero possiamo scegliere tra 3 tipi di login:

•    Basic, l’autenticazione standard del protocollo http
•    Digest, l’autenticazione on criptazione della password
•    Form, per l’autenticazione tramite una form standard che deve essere poi configurata a parte

Infine dobbiamo definire le security-constraint che definiscono l’accesso alle risorse in base al ruolo dell’utente; quindi scriveremo all’interno del resin-web.xml :

<security-constraint url-pattern='/*' role-name='user'/>

In questa direttiva abbiamo stabilito che solo gli utenti con ruolo “user” possono accedere a tutta l’applicazione. Utilizzando degli url-pattern più specifici possiamo fare in modo di richiedere l’autenticazione solo per alcune porzioni di applicazione. Se ora tentiamo di accedere all’applicazione otteniamo:

Fig 7 - Autenticazione

digitando le opportune credenziali avremo accesso all’applicazione.



Performance top
 
Resin, nella versione commerciale, vanta alte prestazioni grazie alle ottimizzazioni fornite da alcune librerie JNI; inoltre supporta il proxy caching, e un motore XSLT circa tre volte più veloce di Xalan e 80% più veloce di Saxon. Come abbiamo già accennato la parte JNI di Resin viene compilata in fase di installazione per i sistemi Unix, mentre per Windows è formata da dll precompilate. Tali librerie JNI vengono utilizzate nelle attività critiche come l’utilizzo delle socket e l’accesso ai file. Inoltre JNI viene utilizzato per interfacciarsi con le librerie di OpenSSL.
Di seguito un benchmark che mette a confronto Resin con altri Server Open Source:

Fig 8 - Resin e gli altri Server Open Source

I valori esprimono il numero di risorse servite in un arco di tempo prestabilito.



Clustering top

 
In ambienti di produzione con traffico molto elevato si rende necessario l’utilizzo del cluster ovvero di un gruppo di istanze di resin che erogano il medesimo servizio collaborando tra loro. Il cluster oltre a distribuire il carico secondo determinate politiche di amministrazione, permette anche di gestire il failover facendo uso della persistenza e la distribuzione dello stato della sessione HTTP.

Per utilizzare il cluster dobbiamo gestire il bilanciamento del carico tra le varie istanze di Resin; abbiamo tre possibilità:

1.    Hardware load ballancing
2.    Load balancing tramite Resin
3.    Load balancing tramite Web Server plugin

L’hardware load balancing prevede l’utilizzo di un bilanciatore (un hardware di rete specializzato) il quale distribuisce il carico tra i vari server pilotando verso un solo server le richieste provenienti dallo stesso IP.
La  tipica configurazione utilizza lo stesso resin.conf per tutte le istanze di Resin che compongono il cluster:

<resin xmlns="http://caucho.com/ns/resin">
  ...
<server>
  <cluster>
    <srun server-id="a" host="127.0.0.1" port="6802"/>
    <srun server-id="b" host="127.0.0.1" port="6803"/>
  </cluster>  
    
  <!-- The http port -->
  <http server-id="a" host="127.0.0.1" port="8080"/>
  <http server-id="b" host="127.0.0.1" port="9090"/>

  ...
</server>
</resin>

Questa configurazione prevede l’utilizzo di due istanze di Resin sulla medesima macchina; il bilanciatore invierà le chiamate alla nostra macchina sulle porte di back end 6802 e 6803. Per avviare ogni singola istanza di Resin dobbiamo usare il flag “-server” che specifica quale server del cluster vogliamo far partire. Sui sistemi unix utilizzeremo quindi i seguenti comandi:

$> bin/httpd.sh -server a -pid server-a.pid start
$> bin/httpd.sh -server b -pid server-b.pid start

Sui sistemi windows avremo invece:

C:\resin-pro-3.0.15>httpd.exe -server a
C:\resin-pro-3.0.15>httpd.exe -server b

L’idea del load balancing tramite Resin è quella di utilizzare un’istanza di Resin come bilanciatore; Resin fornisce una LoadBalanceServlet che viene utilizzata come front-end per bilanciare le richieste verso dei server di back-end. La configurazione dei server di back-end rispecchia quella vista precedentemente per l’hardware load balancing, mentre la configurazione del front end sarà la seguente:

<resin xmlns="http://caucho.com/ns/resin">
  ...
<server>
  <http server-id="front" port='80'/>

  <cluster-definition id="a">
    <srun server-id='back1' host='127.0.0.1' port='6802' index='1'/>
    <srun server-id='back2' host='127.0.0.1' port='6803' index='2'/>
  </cluster-definition>
  ...
  <host id=''>
    <web-app id='/'>
      <!-- balance all requests to the servers in cluster a -->
      <servlet>
        <servlet-name>balance-a</servlet-name>
        <servlet-class>com.caucho.servlets.LoadBalanceServlet</servlet-class>
        <init cluster='a'/>
      </servlet>

      <servlet-mapping url-pattern='/*' servlet-name='balance-a'/>
    </web-app>
  </host>
</server>


Nel server Resin di front-end tutte le chiamate vengono mappate sulla LoadBalanceServlet la quale a sua volta viene configurata con l’id del cluster definito nel tag cluster-definition. La servlet funge da bilanciatore software inoltrando le chiamate verso i nodi del cluster, e pilotando le richieste provenienti dallo stesso IP sempre sullo stesso server. E’ possibile anche definire più cluster e utilizzare più istanze della LoadBalanceServlet che pilotano le richieste sui vari cluster in base all’url-pattern definito.
Se accediamo al nostro server Resin utilizzando come front end un Web Server come Apache o IIS la distribuzione del carico sul cluster viene fatta direttamente dal plugin di Resin. Il plugin del Web server richiede la configurazione del cluster direttamente ad una delle istanze di Resin del cluster; quindi nella configurazione del Web server avremo:

ResinConfigServer 127.0.0.1 6802

Tramite questa direttiva il Web Server interroga Resin che fornirà i parametri delle istanze del cluster su cui inoltrare le richieste.
La persistenza della sessione e la distribuzione della stessa sono punti chiave nell’affidabilità del cluster; Resin fornisce diverse soluzioni:

•    File Based
•    Database Based   
•    Cluster Based

La persistenza della sessione File based permette di salvare lo stato della sessione http su un file; è la soluzione meno praticata in quanto se i server del cluster risiedono su diverse macchine è necessario un NFS condiviso in cui salvare la sessione.  Per abilitare il salvataggio della sessione nel file resin.conf inseriamo:

<resin xmlns="http://caucho.com/ns/resin">
<server>
  <persistent-store type="file">
    <init>
      <path>sessions</path>
    </init>
  </persistent-store>

  ...
</server>
</resin>    

Un modo più efficiente per distribuire la sessione tra le varie istanze dei server del cluster è quello di utilizzare la persistenza tramite database; in questo la caso è necessario definire il datasource in cui verrà salvata la sessione:

<resin xmlns="http://caucho.com/ns/resin">
<server>
  <database jndi-name="java:comp/env/jdbc/session_db">
    ...
  </database>

  <persistent-store type="jdbc">
    <init>
      <data-source>java:comp/env/jdbc/session_db</data-source>
    </init>
  </persistent-store>

  ...
</server>
</resin>

Sul database specificato nel datasource deve essere creata manualmente la seguente tabella:

CREATE TABLE persistent_session (
  id VARCHAR(64) NOT NULL,
  data BLOB,
  access_time TIMESTAMP,
  expire_interval int(11),
  PRIMARY KEY(id)
)

La persistenza cluster based sfrutta le istanze del cluster per replicare la sessione. Ogni sessione ha un server primario e uno di backup. I due application server salvano la sessione aggiornandosi automaticamente ogni volta che questa viene modificata; se il server primario fallisce il client viene rediretto sul server di backup; al restart del server primario la sessione gli viene passata da quello di backup. Nel resin.conf scriveremo:   
  
<resin xmlns="http://caucho.com/ns/resin">
<server>
    ...

  <persistent-store type="cluster">
    <init>
      <path>sessions</path>
    </init>
  </persistent-store>

  ...
</server>
</resin>

Per sfruttare la persistenza della sessione è necessario abilitarla per ogni web application inserendo il tag use-persistent-store nel web.xml :

<web-app xmlns="http://caucho.com/ns/resin">
  <session-config>
    <use-persistent-store="true"/>
  </session-config>
</web-app>

A questo punto se avete messo in pratica il cluster secondo gli esempi precedenti usando il front-end Resin o il front-end Web Server potete utilizzare la seguente JSP per verificare il corretto funzionamento della persistenza della sessione http nel cluster:

<%@ page language="java" import="java.util.* " %>
<%

String nomeHost = "Host non trovato";
HttpSession hs = request.getSession();
   String nuovoAtt = (String)request.getParameter("attributo");
   if (nuovoAtt != null){
   hs.setAttribute(nuovoAtt,(String)request.getParameter("valore"));
   }
int i = request.getLocalPort();
if (i==6802) nomeHost = "Server A";
if (i==6803) nomeHost = "Server B";
%>
Host : <%= nomeHost %> <br/>
id sessione : <%= hs.getId() %> <br/>
Contenuto Sessione:<br>
<%
   Enumeration e = hs.getAttributeNames();
   String nomeAtt = null;
   String att = null;
   while (e.hasMoreElements()) {
   nomeAtt = (String)e.nextElement();
   att = (String) hs.getAttribute(nomeAtt);
%>
attributo: <%= nomeAtt %> = <%= att %> <br> 
<%  
   }
%>
<form method="get"
 action="http://localhost/provaCluster/sessionVerify.jsp"
 name="miaForm">
 nome  <input name="attributo">
 valore <input name="valore">
<input type="submit">
</form>

Questa JSP stampa il server di provenienza l’id della sessione e il suo contenuto; permette inoltre di inserire delle stringhe in sessione. Richiamando la JSP e avviando alternativamente i server del cluster, oppure abilitando e disabilitando la persistenza della sessione, possiamo rilevare come risponde il cluster nelle varie casistiche.
 


Conclusioni e ringraziamenti top

 
Abbiamo effettuato una rapida carrellata sulle principali feature dell’Application Server Resin ma Resin offre molte altre funzionalità che meritano di essere approfondite. Per questo potete consultare la documentazione contenuta sul sito www.caucho.com. Resin si sta imponendo all’attenzione del mercato per essere un prodotto agile e di facile utilizzo, corredato di tutte le funzioni necessarie, e anche per i suoi costi contenuti. Speriamo quindi di aver attirato la vostra attenzione su questo Application Server. Ringraziamo la Caucho Technology, ed in particolare Steve Montal, per il supporto fornito durante la stesura dell’articolo.

Thanks
Thanks to Caucho Technology, and in particular Steve Montal, for the support supplied during the drawing up of the article.





JavaPortal è ideato da:    
K-Tech Logo










LICENZA



Eccetto dove diversamente specificato, i contenuti di questo sito sono rilasciati sotto licenza Creative Commons

Sitemap  © 2002-2004 Copyright Information. Privacy . Today is sabato 19 giugno 2010