domenica 16 ottobre 2011

Java Ajax e JSON

In questo post vediamo come realizzare una semplice applicazione web che gestisce entità di dati in visualizzazione come lista e come inserimento e dettaglio.
Per gestire al meglio i risultati in formato tabellare utilizziamo JSON.
Il contenuto del div può essere popolato dinamicamente lato Ajax con:
  • Codice HTML;
  • XML;
  • JSON.
In questo esempio, preso dall'articolo presente su HTML.it (link articolo), si può vedere come realizzare il servizio utilizzando JSON per la lettura dei dati.
Per generare lato server, dato l'oggetto Java, l'oggetto JSON corrispondente si utilizza la libreria jabsorb-1.3.1.jar .
Tale libreria va posta dentro la directory lib del progetto web assieme anche alle seguenti altre librerie ( altrimenti con compila perchè sono jar utilizzati da questa libreria):

commons-logging-1.1.1.jar       slf4j-jdk14-1.6.2.jar
jabsorb-1.3.1.jar               slf4j-jdk14-1.6.2-sources.jar
jul-to-slf4j-1.6.2.jar          slf4j-log4j12-1.6.2.jar
jul-to-slf4j-1.6.2-sources.jar  slf4j-log4j12-1.6.2-sources.ja
r
slf4j-api-1.6.2.jar             slf4j-migrator-1.6.2.jar
slf4j-api-1.6.2-sources.jar     slf4j-nop-1.6.2.jar
slf4j-ext-1.6.2.jar             slf4j-nop-1.6.2-sources.jar
slf4j-ext-1.6.2-sources.jar     slf4j-simple-1.6.2.jar
slf4j-jcl-1.6.2.jar             slf4j-simple-1.6.2-sources.jar
slf4j-jcl-1.6.2-sources.jar


Lato client invece si utilizzano le API native di Javascript in particolare la
JSON.parse (quindi gli esempi non funzionano con IE 7 e precedenti, per cui sarebbe necessario utilizzare la funzione eval di Javascript).
Ho trovato molto comodo lato js la lettura delle liste dati create in formato JSON lato server,il  viceversa invece molto meno.
Nell'esempio dell'articolo citato si invitava infatti ad utilizzare JSON anche come input al metodo di inserimento, in questo caso ho trovato molto più semplice inviare al server direttamente i parametri e poi inserirli per creare l'articolo piuttosto che creare l'oggetto JSON.

 Di seguito posto tutto il codice utilizzato.


L'entità dati trattata è l'oggetto Java Articolo così definito:

public class Articolo {
    private String articolo;
    private boolean pubblicato;
    private boolean interessante;
    private int [] data;
    private Info info;
.... getter e setter

L'oggetto Info è definito invece così:

public class Info {
private String autore;
... getter e setter
  }

Le operazioni da effettuare sull'entità sono definite dalla seguente interfaccia:


public interface ArticoloManager {
   
    public List<Articolo> getAllArticles();
    public Articolo getArticolo(String id);
    public void insertArticolo(Articolo a);

}
L'implementazione dell'interfaccia è così definita (per semplicita si evita di andare su db e si caricano i dati direttamente in RAM):



public class ArticoloManagerMockImpl implements ArticoloManager {
private static ArticoloManagerMockImpl istanza;
public static ArticoloManagerMockImpl getInstance(){
if(istanza==null)
{
istanza=new ArticoloManagerMockImpl();
}
return istanza;
}
private void caricaLista(){
l.add(generaArticolo("bianchi", "1", new int[]{12,4,1978}));
l.add(generaArticolo("rossi", "2", new int[]{12,4,1985}));
l.add(generaArticolo("verdi", "3", new int[]{10,4,1978}));
l.add(generaArticolo("viola", "4", new int[]{12,9,1978}));
l.add(generaArticolo("cutini", "5", new int[]{31,4,1920}));
}
private Articolo generaArticolo(String autore,String articolo,int[] dataN){
Articolo a=new Articolo();
Info a1=new Info();
a1.setAutore(autore);
a.setArticolo(articolo);
a.setData(dataN);
a.setInteressante(true);
a.setPubblicato(true);
a.setInfo(a1);
return a;
}
private ArticoloManagerMockImpl(){
caricaLista();
}
private List<Articolo> l=new ArrayList<Articolo>();
@Override
public List<Articolo> getAllArticles() {
// TODO Auto-generated method stub
return l;
}

@Override
public Articolo getArticolo(String id) {
Articolo ret=null;
for(Articolo a:l){
if(id.equals(a.getArticolo()))
{
ret=a;
break;
}
}
return ret;
}

@Override
public void insertArticolo(Articolo a) {
l.add(a);

}

}



JSP

Lato Web ho una semplice JSP così definita:


<%@ page language="java" contentType="text/html; charset=UTF-8"
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">
<script type="text/javascript" src="${pageContext.request.contextPath}/js/util.js"></script>
<title>Insert title here</title>
</head>
<body>
<form >
<table>
<tr><td>Articolo: </td><td><input type="text" name="txtArticolo" id="txtArticolo"/></td></tr>
<tr><td>Autore: </td><td><input type="text" name="txtAutore" id="txtAutore"/></td></tr>
<tr><td>Data: </td><td><input type="text" name="txtData" id="txtData"/></td></tr>
</table>
<input type="button" value="Visualizza Tutti" onclick="javascript:estraiTutti('${pageContext.request.contextPath}/Gestione')"/>
&nbsp;&nbsp;&nbsp;
<input type="button" value="Inserisci" onclick="javascript:insert('${pageContext.request.contextPath}/Gestione')"/>
&nbsp;&nbsp;&nbsp;
<input type="button" value="Cerca per Id Articolo" onclick="javascript:getById('${pageContext.request.contextPath}/Gestione')"/>

</form>
<div id="lista">
</div>
<div id="inserimento"></div>
<div id="dettaglio"></div>
</body>
</html>


I tre div lista inserimento e dettaglio servono a visualizzare o la lista risultati oppure il messaggio di inserimento ok oppure il dettaglio di una entità inserita (cerca per codice articolo).

Servlet

La servlet richiamata via Ajax è la seguente, Notare che alla fine ho utilizzato il metodo insertArticle invece di insertArticleJson suggerito dall'articolo di HTML.


public class Gestione extends HttpServlet {
private static final long serialVersionUID = 1L;
ArticoloManager interfaccia;
JSONSerializer serializer;
/**
* @see HttpServlet#HttpServlet()
*/
public Gestione() {
super();
// TODO Auto-generated constructor stub
}
public void init()
{
serializer = new JSONSerializer();
interfaccia = ArticoloManagerMockImpl.getInstance();
try
{
// inizializza i tipi serializzatori forniti
// di default con la libreria
serializer.registerDefaultSerializers();
}
catch (Exception e)
{
e.printStackTrace();
}
}

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
private void processRequest(HttpServletRequest request, HttpServletResponse response)
{
try
{
String op = request.getParameter("op");
if (op != null)
{
if (op.equalsIgnoreCase("listAllArticles")) listAllArticles(request, response);
else if (op.equalsIgnoreCase("listArticle")) listArticle(request, response);
else if (op.equalsIgnoreCase("insert")) insertArticle(request, response);
}
// op è null
}
catch(Exception ex){
}
}

private void listArticle(HttpServletRequest request, HttpServletResponse response)
throws NumberFormatException, IOException, MarshallException
{
String articoloId = request.getParameter("articolo");
// Usa la logica esistente per recuperare l'articolo
Articolo toRet = interfaccia.getArticolo(articoloId);
List<Articolo> l=new ArrayList<Articolo>();
l.add(toRet);
// restituisce l'articolo serializzato in JSON tramite
// l'oggetto serializer
response.getWriter().println(serializer.toJSON(l.toArray()));
}
private void listAllArticles(HttpServletRequest request, HttpServletResponse response)
throws NumberFormatException, IOException, MarshallException
{
// Recupera gli articoli con la logica esistente
List<Articolo> toRet = interfaccia.getAllArticles();
// returns a JSON
response.getWriter().println(serializer.toJSON(toRet.toArray()));
}
private String streamToString(InputStream in) throws IOException
{
StringBuffer out = new StringBuffer();
byte[] b = new byte[4096];
for (int n; (n = in.read(b)) != -1;) {
out.append(new String(b, 0, n));
}
return out.toString();
}
/*
* Restituisce un Articolo in formato JSON
*
* Parametri attesi: op, operazione
*/
private void insertArticleJson(HttpServletRequest request, HttpServletResponse response)
throws NumberFormatException, IOException, MarshallException, UnmarshallException
{
// riceve il messaggio JSON da POST
String json = streamToString(request.getInputStream());
// lo de-serializza
Articolo newArticle = (Articolo) serializer.fromJSON(json);
// inserisce l'articolo ricevuto nel DB
interfaccia.insertArticolo(newArticle);
response.getWriter().println("Ok inserito");
}
private void insertArticle(HttpServletRequest request, HttpServletResponse response)
throws NumberFormatException, IOException, MarshallException, UnmarshallException
{
String articolo=request.getParameter("articolo");
String autore=request.getParameter("autore");
String data=request.getParameter("txtData");
String[] dati=data.split("/");
int anno=Integer.valueOf(dati[2]);
int mese=Integer.valueOf(dati[1]);
int giorno=Integer.valueOf(dati[0]);
int[] arrData=new int[3];
arrData[0]=giorno;
arrData[1]=mese;
arrData[2]=anno;
Articolo art=new Articolo();
Info i=new Info();
i.setAutore(autore);
art.setArticolo(articolo);
art.setInfo(i);
art.setData(arrData);
art.setInteressante(true);
art.setPubblicato(true);
interfaccia.insertArticolo(art);
response.getWriter().println("Ok inserito");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}

}

  JAVASCRIPT



function getXMLHttpRequest() {
try {

return new XMLHttpRequest();
} catch (e) {
try {

return new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {
try {
return new ActiveXObject('MSXML2.XMLHTTP.3.0');
} catch(e) {alert('errore');}
}
}
return null;
}
function getJsonResult(risultato)
{
var result="";
var i;
try
{
var my_JSON_object = JSON.parse(risultato);
result="<table border='1'><tr><td>Articolo</td><td>Autore</td><td>Data</td></tr>";
for( i=0;i<my_JSON_object.length;i++){
result+="<tr>";
result+="<td>";
result+=my_JSON_object[i].articolo;
result+="</td>";
result+="<td>";
result+=my_JSON_object[i].info.autore;
result+="</td>";
result+="<td>";
result+=my_JSON_object[i].data;
result+="</td>";
result+="</tr>";
}
result+="</table>";
return result;
}
catch(err){
alert(err);
}
}
function insert(url){
var xmlHttp=getXMLHttpRequest();
xmlHttp.onreadystatechange=function (){
if(xmlHttp.readyState==4){
if(xmlHttp.status==200 || xmlHttp.status==0){
var risultatoTxt=xmlHttp.responseText;
var dett=document.getElementById("dettaglio");
var list=document.getElementById("lista");
var ins=document.getElementById("inserimento");
dett.innerHTML="";
list.innerHTML="";
ins.innerHTML="";
ins.innerHTML=risultatoTxt;
}
else
{
alert('Comunicazione fallita '+xmlHttp.status+" Motivo: "+xmlHttp.statusText);
}
}
};
xmlHttp.open("POST",url,false);
xmlHttp.setRequestHeader("content-type", "application/x-www-form-urlencoded");
xmlHttp.setRequestHeader("connection", "close");
var txtArticolo=document.getElementById("txtArticolo").value;
var txtAutore=document.getElementById("txtAutore").value;
var txtData=document.getElementById("txtData").value;
xmlHttp.send("op=insert&articolo="+txtArticolo+"&autore="+txtAutore+"&txtData="+txtData);
}
function getById(url){
var xmlHttp=getXMLHttpRequest();
xmlHttp.onreadystatechange=function (){
if(xmlHttp.readyState==4){
if(xmlHttp.status==200 || xmlHttp.status==0){
var risultatoTxt=xmlHttp.responseText;
var dett=document.getElementById("dettaglio");
var list=document.getElementById("lista");
var ins=document.getElementById("inserimento");
dett.innerHTML="";
list.innerHTML="";
ins.innerHTML="";
dett.innerHTML=getJsonResult(risultatoTxt);
}
else
{
alert('Comunicazione fallita '+xmlHttp.status+" Motivo: "+xmlHttp.statusText);
}
}
};
xmlHttp.open("POST",url,false);
xmlHttp.setRequestHeader("content-type", "application/x-www-form-urlencoded");
xmlHttp.setRequestHeader("connection", "close");
var txtArticolo=document.getElementById("txtArticolo").value;
xmlHttp.send("op=listArticle&articolo="+txtArticolo);
}
function estraiTutti( url){
var xmlHttp=getXMLHttpRequest();
xmlHttp.onreadystatechange=function (){
if(xmlHttp.readyState==4){
if(xmlHttp.status==200 || xmlHttp.status==0){
var risultatoTxt=xmlHttp.responseText;
var dett=document.getElementById("dettaglio");
var list=document.getElementById("lista");
var ins=document.getElementById("inserimento");
dett.innerHTML="";
list.innerHTML="";
ins.innerHTML="";
list.innerHTML="";
list.innerHTML=getJsonResult(risultatoTxt);
}
else
{
alert('Comunicazione fallita '+xmlHttp.status+" Motivo: "+xmlHttp.statusText);
}
}
};
xmlHttp.open("POST",url,false);
xmlHttp.setRequestHeader("content-type", "application/x-www-form-urlencoded");
xmlHttp.setRequestHeader("connection", "close");
xmlHttp.send("op=listAllArticles");
}


Risultato finale




 

giovedì 13 ottobre 2011

Installare Jboss 4 e Jboss 5 come servizi di windows

Per Jboss4 è necessario scaricarsi dal sito di Jboss il pacchetto jbosseNative ( http://www.jboss.org/jbossweb/downloads/jboss-native-2-0-9.html ) .
Per Jboss 5 invece la directory bin ha già tutto quello che serve.
A questo punto una volta scompattato nella directory bin dobbiamo agire a livello di service.bat.
Qui c'è la sezione


set SVCNAME=JBAS50SVC
set SVCDISP=JBoss Application Server 5.0
set SVCDESC=JBoss Application Server 5.0.0 GA/Platform: Windows x86
E si può personalizzare il nome del servizio (SVCDISP e SVCNAME).
Il file service.bat può essere personalizzato anche nel punto in cui si chiama il run.bat ossia qui
jbosssvc.exe -p 1 "Starting %SVCDISP%" > run.log
call run.bat -c all -b 127.0.0.1 < .r.lock >> run.log 2>&1
jbosssvc.exe -p 1 "Shutdown %SVCDISP% service" >> run.log
 Il file run.log rappresenta il file in cui è scritto l'output di console.

Se vogliamo eseguire un'altra istanza di Jboss sullo stesso server allora (dopo averla configurata opportunatamente, vedi post) dobbiamo copiare il file service.bat, rinominarlo ad esempio service2.bat e cambiare i dettagli del nome servizio e della chiamata al .bat (es. call run.bat -c nuovaIstanza .....). 
Bisogna cambiare quindi sia il SVCNAME che il SVCDISP obbligatoriamente, la desrizione è facoltativa ma sempre meglio personalizzarla.
Per far partire il servizio da console digitare
JBOSS_HOME/bin> service.bat install
Per stoppare il servizio da console digitare

JBOSS_HOME/bin> service.bat uninstall
Nei servizi di Windows apparirà così:


Incollo il testo del serviceProfiler.bat un bat che ho utilizzato per far coesistere sullo stesso server due istanze dello stesso Jboss come servizio (il nome dell'istanza da far partire era profile) :

@echo off
REM JBoss, the OpenSource webOS
REM
REM Distributable under LGPL license.
REM See terms of license at gnu.org.
REM
REM -------------------------------------------------------------------------
REM JBoss Service Script for Windows
REM -------------------------------------------------------------------------


@if not "%ECHO%" == "" echo %ECHO%
@if "%OS%" == "Windows_NT" setlocal
set DIRNAME=%CD%

REM
REM VERSION, VERSION_MAJOR and VERSION_MINOR are populated
REM during the build with ant filter.
REM
set SVCNAME=JBAS50SVCPROF
set SVCDISP=JBoss AS-ProfilerDemo
set SVCDESC=JBoss Application Server 5.0.0 GA/Platform: Windows x86
set NOPAUSE=Y

REM Suppress killing service on logoff event
set JAVA_OPTS=-Xrs

REM Figure out the running mode

if /I "%1" == "install"   goto cmdInstall
if /I "%1" == "uninstall" goto cmdUninstall
if /I "%1" == "start"     goto cmdStart
if /I "%1" == "stop"      goto cmdStop
if /I "%1" == "restart"   goto cmdRestart
if /I "%1" == "signal"    goto cmdSignal
echo Usage: service install^|uninstall^|start^|stop^|restart^|signal
goto cmdEnd

REM jbosssvc retun values
REM ERR_RET_USAGE           1
REM ERR_RET_VERSION         2
REM ERR_RET_INSTALL         3
REM ERR_RET_REMOVE          4
REM ERR_RET_PARAMS          5
REM ERR_RET_MODE            6

:errExplain
if errorlevel 1 echo Invalid command line parameters
if errorlevel 2 echo Failed installing %SVCDISP%
if errorlevel 4 echo Failed removing %SVCDISP%
if errorlevel 6 echo Unknown service mode for %SVCDISP%
goto cmdEnd

:cmdInstall
jbosssvc.exe -imwdc %SVCNAME% "%DIRNAME%" "%SVCDISP%" "%SVCDESC%" serviceProfile.bat
if not errorlevel 0 goto errExplain
echo Service %SVCDISP% installato
goto cmdEnd

:cmdUninstall
jbosssvc.exe -u %SVCNAME%
if not errorlevel 0 goto errExplain
echo Service %SVCDISP% rimosso
goto cmdEnd

:cmdStart
REM Executed on service start
del .rProfile.lock 2>&1 | findstr /C:"being used" > nul
if not errorlevel 1 (
  echo Could not continue. Locking file already in use.
  goto cmdEnd
)
echo Y > .rProfile.lock
jbosssvc.exe -p 1 "Starting %SVCDISP%" > run_Profile.log
call run.bat -c profile < .rProfile.lock >> run_Profile.log 2>&1
jbosssvc.exe -p 1 "Shutdown %SVCDISP% service" >> run_Profile.log
del .rProfile.lock
goto cmdEnd

:cmdStop
REM Executed on service stop
echo Y > .sProfile.lock
jbosssvc.exe -p 1 "Shutting down %SVCDISP%" > shutdownProfile.log
call shutdown -S < .sProfile.lock >> shutdownProfile.log 2>&1
jbosssvc.exe -p 1 "Shutdown %SVCDISP% service" >> shutdownProfile.log
del .sProfile.lock
goto cmdEnd

:cmdRestart
REM Executed manually from command line
REM Note: We can only stop and start
echo Y > .sProfile.lock
jbosssvc.exe -p 1 "Shutting down %SVCDISP%" >> shutdownProfile.log
call shutdown -S < .sProfile.lock >> shutdownProfile.log 2>&1
del .sProfile.lock
:waitRun
REM Delete lock file
del .sProfile.lock > nul 2>&1
REM Wait one second if lock file exist
jbosssvc.exe -s 1
if exist ".sProfile.lock" goto waitRun
echo Y > .sProfile.lock
jbosssvc.exe -p 1 "Restarting %SVCDISP%" >> runProfile.log
call run.bat < .sProfile.lock >> run.log 2>&1
jbosssvc.exe -p 1 "Shutdown %SVCDISP% service" >> runProfile.log
del .sProfile.lock
goto cmdEnd

:cmdSignal
REM Send signal to the service.
REM Requires jbosssch.dll to be loaded in JVM
@if not ""%2"" == """" goto execSignal
echo Missing signal parameter.
echo Usage: service signal [0...9]
goto cmdEnd
:execSignal
jbosssvc.exe -k%2 %SVCNAME%
goto cmdEnd

:cmdEnd


mercoledì 12 ottobre 2011

Javascript aggiungere un link ai preferiti

Purtroppo le istruzioni per aggiungere un link ai preferiti via javascript cambiano da Browser a browser.
Il seguente metodo javascript si occupa di effettuare l'operazione sui due browser più utilizzati, Internet Explorer e Firefox.

Il codice è il seguente

function addFav(link,name)
{
    if (window.sidebar) { // Mozilla Firefox Bookmark
                      window.sidebar.addPanel(name, link,"");
                         } else if( window.external ) 

{ // IE Favorite
        window.external.AddFavorite( link, name);

}
}


Di seguito vediamo un esempio html:

Sito inter
Corriere della Sera
Repubblica




giovedì 6 ottobre 2011

Sistema profilatura utente con Java Tomcat e MySql


Nel seguente post vediamo come realizzare un sistema di profilatura utente basandoci sulle possibilità di configurazione di sicurezza lato web.xml.
L’obbiettivo è avere a disposizione su una base dati la lista degli utenti e dei ruoli e chiedere l’autenticazione utente per proteggere l’accesso indesiderato alle pagine del nostro sito.
Come application server ho usato tomcat versione 7.0.19, come database MySql versione 5.5.12.

Nell’esempio di test vediamo una sola pagina con due link e 2 ruoli, uno di amministratore ed uno di visualizzatore.
L’amministratore li visualizza entrambi,  il visualizzatore soltanto uno.

Lato web.xml dobbiamo quindi inserire le seguenti configurazioni

<login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>Autenticazione Servizio Profilatura</realm-name>
  </login-config>
  <security-constraint>
      <web-resource-collection>
            <web-resource-name>restricted methods</web-resource-name>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
      </web-resource-collection>
      <auth-constraint>
      <role-name>ADMIN</role-name>
      <role-name>VIS</role-name>
      </auth-constraint>
</security-constraint>
  <security-role>
  <role-name>ADMIN</role-name>
  </security-role>
  <security-role>
  <role-name>VIS</role-name>
  </security-role>

In questo caso utilizziamo l’autenticazione di tipo BASIC (comparirà la maschera di pop up del browser chiedendo le credenziali).
Abbiamo stabilito nel security constraint che tutte le pagine dell’applicativo saranno sottoposte a sicurezza (nodo url-pattern) e che i metodi sottoposti a sicurezza saranno sia il GET che il POST.

I ruoli che possono accedere alle pagine (nodo auth-constraint) sono due, ADMIN e VIS (specificati poi come security role).
Si noti che se non si mette il nodo auth-constraint nessuno sarà abilitato a vedere nulla sull’applicazione e comparirà sempre l’errore http 403 (access forbidden).

A questo punto scriviamo anche la jsp con i due link per testare i ruoli.
Il codice è il seguente:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
   
 <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<!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>Profilatura</title>
</head>
<body>
<% if(request.isUserInRole("ADMIN")){ %>
<a href="jsp/InserisciUtente.jsp" >Inserisci Utente</a>
<% } %>
<br>
<a href="jsp/GestioneUtenti.jsp" >Gestioni Utente</a>
</body>
</html>

Con il metodo request.isUserInRole possiamo accedere al ruolo dell’utente e soltanto l’amministratore potrà visualizzare il link “Inserisci Utente”.

A questo punto dobbiamo creare il nostro data base.

Lo script per la creazione del db, che si compone di 3 tabelle , una utenti una ruoli ed una associativa utenti ruoli.

Di seguito lo script:
CREATE DATABASE IF NOT EXISTS tomcat_realm;
USE tomcat_realm;

--
-- Definition of table `tomcat_roles`
--

DROP TABLE IF EXISTS `tomcat_roles`;
CREATE TABLE `tomcat_roles` (
  `role_name` varchar(20) NOT NULL,
  PRIMARY KEY (`role_name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `tomcat_roles`
--

/*!40000 ALTER TABLE `tomcat_roles` DISABLE KEYS */;
INSERT INTO `tomcat_roles` (`role_name`) VALUES
 ('ADMIN'),
 ('VIS');
/*!40000 ALTER TABLE `tomcat_roles` ENABLE KEYS */;


--
-- Definition of table `tomcat_users`
--

DROP TABLE IF EXISTS `tomcat_users`;
CREATE TABLE `tomcat_users` (
  `user_name` varchar(20) NOT NULL,
  `password` varchar(32) NOT NULL,
  PRIMARY KEY (`user_name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `tomcat_users`
--

/*!40000 ALTER TABLE `tomcat_users` DISABLE KEYS */;
INSERT INTO `tomcat_users` (`user_name`,`password`) VALUES
 ('kermit','thefrog'),
 ('sfigato','sfigato');
/*!40000 ALTER TABLE `tomcat_users` ENABLE KEYS */;


--
-- Definition of table `tomcat_users_roles`
--

DROP TABLE IF EXISTS `tomcat_users_roles`;
CREATE TABLE `tomcat_users_roles` (
  `user_name` varchar(20) NOT NULL,
  `role_name` varchar(20) NOT NULL,
  PRIMARY KEY (`user_name`,`role_name`),
  KEY `tomcat_users_roles_foreign_key_2` (`role_name`),
  CONSTRAINT `tomcat_users_roles_foreign_key_1` FOREIGN KEY (`user_name`) REFERENCES `tomcat_users` (`user_name`),
  CONSTRAINT `tomcat_users_roles_foreign_key_2` FOREIGN KEY (`role_name`) REFERENCES `tomcat_roles` (`role_name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `tomcat_users_roles`
--

/*!40000 ALTER TABLE `tomcat_users_roles` DISABLE KEYS */;
INSERT INTO `tomcat_users_roles` (`user_name`,`role_name`) VALUES
 ('kermit','ADMIN'),
 ('sfigato','VIS');

Ora dobbiamo agganciare il tomcat al db per fare in modo che cerchi in quel realm e non nel realm di default, che è quello costituito dal file xml tomcat-users.xml, che si trova sotto la directory conf.

Quindi i passi da seguire sono 2:

  • Inserire il mysql-connector-java-3.0.17-ga-bin.jar (connettore jdbc di Mysql) sotto la directory di tomcat [ROOT]/lib;
  • Modificare il file [ROOT]/conf/server.xml.

Per il punto 2 occorre decommentare il Realm standard e sostituirlo con il nuovo, in questo modo:

<!--
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>
        -->
      <Realm  className="org.apache.catalina.realm.JDBCRealm"
             driverName="com.mysql.jdbc.Driver"
          connectionURL="jdbc:mysql://localhost:3306/tomcat_realm"
         connectionName="root" connectionPassword="root"
              userTable="tomcat_users" userNameCol="user_name" userCredCol="password"
          userRoleTable="tomcat_users_roles" roleNameCol="role_name" />
              </Realm>




A questo punto deployando l’applicazione sotto la cartella webapps di Tomcat e digitando l’indirizzo http://localhost:8080/ProfileWeb

Compare il pop up di autenticazione




E quindi, poiché l’utenza inserita è di amministratore, si vedranno entrambi i link, viceversa con l’altra utenza se ne vedrà soltanto uno.