martedì 28 gennaio 2014

Errore CertificateException : No subject alternative names present in chiamata HTTPS

Ho passato un pomeriggio a dannarmi per questo errore, ottenuto in fase di chiamata ad un Web Service in HTTPS sulla mia macchina.
Lo scenario è il seguente:
  1. Ho creato un certificato HTTPS;
  2. Lo ho inserito in Tomcat per fare in modo che un mio web service rispondesse in HTTPS;
  3. Ho scritto un client JAVA per il servizio
Il client Java è stato generato con JAX-WS, con il comando wsimport prima che fosse messo in HTTPS il servizio.
L'unica modifica al client fatta è stata quella di creare un costruttore ulteriore che prendesse in input l'url del servizio come Stringa, in modo da poterlo invocare a runtime con il percorso in https.
Cercando quindi l'errore su Internet ho letto che il problema era dato dalla presenza nel CN del certificato di un nome diverso da quello del server invocato lato client; ho letto anche che tale problema si verifica soltanto in caso di certificati self signed.
Ho provato a rigenerare il certificato mettendo nel CN (il primo campo richiesto dalla procedura keytool) l'indirizzo 127.0.0.1 oppure localhost ma nulla da fare, sempre lo stesso errore.
Ho risolto così:
  1. Nel file hosts della mia macchina ho aggiunto un nome XXX mappandolo a 127.0.0.1;
  2. Ho rigenerato il certificato mettendo come nome nel CN lo stesso del punto 1;
  3. Ho effettuato la chiamata client con l'indirizzo http://XXX:8080/URL_WSDL.

Cosìfacendo ha funzionato, anche se non capisco perchè...

domenica 19 gennaio 2014

Esempio utilizzo java.util.concurrent.Future, Callable e ExecutorService

L'interfaccia java.util.concurrent.Future schematizza un oggetto che dovrà tornare in futuro il risultato di una operazione asincrona.
L'interfaccia java.util.concurrent.Executor dichiara un solo metodo, void execute(Runnable)
L'interfaccia java.util.concurrent.ExecutorService estende l'interfaccia Executor aggiungendo funzionalità che consentono il termine dei thread e la produzione di oggetti Future.
L'interfaccia java.util.concurrent.Callable dichiara invece un solo metodo V call() throws Exception

Vediamo un esempio di una classe che implementa Callable e utilizza un ExecutorService per creare un oggetto Future passando il Callable.


package it.threads;
import java.util.concurrent.Callable;
public class OperazioneAsincrona implements Callable<String> {
 @Override
 public String call() throws Exception {
  System.out.println("Simulo lavorazione.....");
  Thread.sleep(3000);
  return "Lavorazione eseguita.....";
 }
}



Vediamo ora come richiamare il callable utilizzando ExecutorService e Future.

package it.threads;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class OperazioneAsincronaTest {
 public static void main(String[] args) throws InterruptedException, ExecutionException {
       Callable<String> task=new OperazioneAsincrona();
       ExecutorService es=Executors.newSingleThreadExecutor();
       Future<String> f=es.submit(task);
       System.out.println(f.get());
       System.out.println("Esco dall'executor...");
       es.shutdown();
 }
}


Si può anche istanziare un ThradPool con l' ExecutorService, usando invece del newSingleThreadExecutor il metodo newFixedThreadPool che accetta come parametro in input un intero.

Esempio utilizzo AtomicInteger

La classe AtomicInteger si trova nel package java.util.concurrent.atomic.
Si utilizza per evitare i problemi di tipo data race nel caso di operazioni multi-thread, quindi garantisce che nel caso di accessi ad un contatore una sincronizzazione sulla variabile da incrementare.
Vediamo un esempio classico di utilizzo di variabili intere in un ambiente multi thread.


package it.threads;
public class ClassicIntTest extends Thread {
 private static Integer intero=new Integer(0);
 public void run(){
  System.out.println("CLASSICO: Incremento 
                e recupero il valore "+ ++intero);
 }
}


Se lanciamo il Thread per 10 volte in questo modo:

public static void main(String[] args) {
  for(int i=0;i<10;i++){
    new ClassicIntTest().start();
  }
 }

Lanciando il main può accadere di avere il seguente output:

CLASSICO: Incremento e recupero il valore 1
CLASSICO: Incremento e recupero il valore 2
CLASSICO: Incremento e recupero il valore 3
CLASSICO: Incremento e recupero il valore 4
CLASSICO: Incremento e recupero il valore 5
CLASSICO: Incremento e recupero il valore 6
CLASSICO: Incremento e recupero il valore 7
CLASSICO: Incremento e recupero il valore 8
CLASSICO: Incremento e recupero il valore 8
CLASSICO: Incremento e recupero il valore 9


Come possiamo vedere il risultato non è quello che ci attenderemmo, in quanto non essendoci sincronizzazione sulla variabile intera (che è statica) capita che 2 thread leggano lo stesso valore in quanto accedono nel medesimo istante al metodo.

Se utilizziamo invece l'AtomicInteger questo non accade.
Esempio:

package it.threads;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntTest extends Thread {
 private static AtomicInteger intero=new AtomicInteger(0);
 public void run(){
  System.out.println("ATOMIC: Incrementa e recupera il valore "+intero.incrementAndGet());
 }
}


Se nel main precedente sostituiamo la classe ClassicIntTest con la AtomicIntTest avremo invece sempre l'output atteso, ossia:

ATOMIC: Incrementa e recupera il valore 1
ATOMIC: Incrementa e recupera il valore 2
ATOMIC: Incrementa e recupera il valore 3
ATOMIC: Incrementa e recupera il valore 4
ATOMIC: Incrementa e recupera il valore 5
ATOMIC: Incrementa e recupera il valore 6
ATOMIC: Incrementa e recupera il valore 8
ATOMIC: Incrementa e recupera il valore 7
ATOMIC: Incrementa e recupera il valore 9
ATOMIC: Incrementa e recupera il valore 10

giovedì 9 gennaio 2014

Modificare il comportamento di default di una textarea sul click tasto enter

Di default una textarea associa l'evento submit del form al click sul tasto enter.
Per dare invece al tasto enter un altro significato è sufficiente agire sull'evento onkeyDown, in modo da aggiungere lo spazio al click sull'enter e prevenendo il comportamento di default.
Per aggiungere il testo a capo facciamo così: 

document.getElementById(event.target.id).innerHTML+="<br />";


Di seguito l'esempio in una  jsp:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!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>Insert title here</title>
</head>
<body>
<form >
 <textarea id="prova"  rows="10" cols="50"></textarea>

</form>
</body>
<script>

document.getElementById("prova").addEventListener("keydown",test,false);

function test(e) {
 
   
     if (e.keyCode == 13  &&  e.target=="[object HTMLTextAreaElement]"  ) {
      document.getElementById(event.target.id).innerHTML+="<br />";
      e.preventDefault();
      return false;
    }
}

</script>
</html>




mercoledì 8 gennaio 2014

Java stampare tutti i get di un oggetto

Un metodo per avere in stampa tutte i getter di un oggetto:


public static String getRappresentazioneStringa(Object o) throws Exception{
   StringBuffer sb=new StringBuffer();
   Method[] listaMetodi= o.getClass().getMethods();
   for(int i=0;i<listaMetodi.length;i++){
    Method m=listaMetodi[i];
    if(m.getName().startsWith("get") && !"getClass".equals(m.getName())){
     // è un getter stampo il valore
     sb.append(m.getName().substring(3).toUpperCase());
     sb.append(" = ");
     sb.append(m.invoke(o)!=null?m.invoke(o).toString():"");
     sb.append("#");
    }
   }
   return sb.toString();
}