domenica 27 ottobre 2013

Trovare tutti i numeri lunghi x-cifre in un campo di testo

Questo metodino cerca in una stringa tutti i valori numerici di 5 cifre in un campo di testo.


String testo2=" cerchiamo i cap 00175 oppure anche 03029, so si 234 09909 carlo";
  Pattern pt=Pattern.compile("\\b\\d{5}\\b");
  Matcher mc=pt.matcher(testo2);
  while(mc.find()){
   System.out.println(mc.group());
  }



Il separatore \b indica il termine parola , quindi becca e riconosce anche le virgole immediatamente dopo, se avessimo usato una espressione regolare del tipo \D\d{5}\D (ossia un qualsiasi carattere non numerico + 5 numeri + qualsiasi carattere non numerico) avremmo preso ad esempio 03029, con la virgola eccetera.

Differenze tra uso dei generics e il tipo object

C'è una sottile differenza tra la notazione con i generics e quella con il tipo generico java.lang.Object
Infatti se scriviamo questo metodo:

public static void stampa(List<?> lista){
  for(Object o:lista){
   System.out.println("["+o+"]");
  }
 }


Possiamo passare ad esso qualsiasi struttura dati ed avere l'output in stampa.
Es:

List<String> ls=new ArrayList<>();
  ls.add("uno");
  ls.add("due");
  ls.add("tre");
  stampa(ls);
  List<Integer> lista=new ArrayList<>();
  lista.add(5);
  lista.add(7);
  lista.add(9);
  stampa(lista);




Se invece proviamo a cambiare la firma del metodo da List<?> a List<Object> il
codice non compila più, il messaggio è "The method stampa(List<Object>) in the type xxxxx is not applicable for the arguments (List<String>) "

dove xxx è il nome della classe da cui invochiamo il metodo.
La differenza quindi tra i due approcci è che usando List<Object>  si incappa nel problema del subtyping, ossia il tipo List<String> poichè String è sottoclasse di object non va bene per invocare il metodo, bisognerà esplicitamente castare il parametro.
La notazione ? ci evita di effettuare cast e il nostro metodo funzionerà con Liste di qualsiasi tipo.

mercoledì 23 ottobre 2013

Java, invocare tutti i set di un metodo con input di tipo Stringa

Un metodo utile per istanziare al volo un oggetto e settare tutte le sue proprietà con input una stringa casuale

public Object getOggettoIstanziato(String nomeClasse) throws Throwable {
Class dynamicClass = null;
dynamicClass = Class.forName(nomeClasse);
Object iClass = dynamicClass.newInstance();
Method[] listaMetodi = dynamicClass.getMethods();
for (Method m : listaMetodi)
{
if (m.getName().startsWith("set")
&& m.getGenericParameterTypes()[0].toString().equals("class java.lang.String"))
{
 int numeroCaratteri = RandomUtils.nextInt(20) + 1;
 m.invoke(iClass,new Object[] { getRandomString(numeroCaratteri) });
   }
  }
  return iClass;
 }

lunedì 21 ottobre 2013

Jquery errore con IE8 SCRIPT65535: Chiamata inattesa al metodo o alla proprietà di accesso

Ho perso tantissimo tempo per risolvere questo problema.
Utilizzavo prime faces versione 3.5 e avevo un p:commandButton che all'oncomplete faceva apparire un p:dialog e aveva poi nell'update settato l'id del form da aggiornare.
In sostanza data una lista di eventi si cliccava su uno di essi e appariva una finestra modale (il p:dialog appunto).
Il codice funzionava senza problemi su IE9 IE10 Firefox e Chrome.
Purtroppo su IE8 invece la finestra modale non si apriva.
Dopo ore di autentica disperazione  ho capito il motivo dell'errore.
Il problema è che in HTML sarebbe illegale (ma è ormai praticamente tollerato da tutti i browser) avere form innnestati l'uno nell'altro.
Le versioni di IE fino alla 8 segnalavano come errore bloccante questa disattenzione.
Quindi , per farla breve, per consentire il funzionamento corretto ho dovuto spostare il tag del form del p:dialog al di fuori del form padre.
Il problema quindi non è di Jquery e neppure di prime faces....
Solo colpa mia

giovedì 10 ottobre 2013

Configurare sicurezza con autenticazione BASIC in IIS 7.5

Essendo nuovo del mondo Microsoft mi sono trovato un pò in difficoltà nel configurare l'autenticazione BASIC su IIS.
La documentazione sul sito Microsoft è esauriente ma sono incappato in alcuni problemi risolti grazie ai forum e alla pazienza.
Per prima cosa occorre installare IIS sulla propria macchina con le principali componenti aggiuntive (filtri ISAPI, ASP net, Autenticazione BASIC compresa che di default non la mette).
Per farlo da Windows 7 procedere in Pannello di controllo/Programmi/Attivazione Disattivazione componenti di Windows e quindi selezionare IIS.

A questo punto, dopo aver creato un semplice Web Service con Visual Studio 2010, task banale, copiare il contenuto del progetto in una directory e da dentro IIS , sul pannello di sinistra, creare un nuovo sito in questo modo:

Quindi specificare il percorso fisico della directory, e fin qui tutto risulta molto intuitivo.

Per prima cosa adesso bisogna configurare la sicurezza sul sito, quindi una volta cliccato sul sito nella parte centrale dello schermo clicchiamo su "Autenticazione"

Qui occorre DISABILITARE l'autenticazione anonima ed abilitare l'autenticazione di base semplicemente selezionando le scelte multiple:


DIFFERENZE CON JAVA

A questo punto una nota importante.
In una web app Java per configurare l'autenticazione basic occorre impostare la security sul web.xml dell'applicazione, utilizzando il nodo < login-config> e quindi il <security-constraint> per vincolare la sicurezza solo ad alcuni metodi o url pattern oppure ruoli.
Sul server poi si attiva il realm inserendo gli utenti abilitati su file o su db.
Con IIS invece bisogna configurare soltanto il server, senza toccare la web app e in più (cosa che mi sembra strana e sono sicuro si possa cambiare ma io non so farlo) gli utenti abilitati possono essere solo utenti abilitati sul pc con pieni diritti sulla cartella.

IMPOSTAZIONE REALM

Si può impostare il realm facendo tasto destro su Autenticazione di base e settando il parametro Area Autenticazione:


In questo caso cercando di entrare nel sito da URL comparirà il seguente prompt del browser
:


PRINCIPALI PROBLEMI RISCONTRATI

Innanzitutto il primo problema è stato attivare la componente ASP net e l'autenticazione BASIC, che come scritto precedentemente non sono installati di default con IIS.

L'errore che si verificava in questo caso diceva chiaramente che non era possibile interpetare gli script, quindi IIS non avendo il modulo asp.net non riusciva ad interpetare le pagine.

Poi ho avuto un problema dovuto al fatto che l'applicazione utilizzava il .NET Framework 4.0 mentre il default di IIS 7.5 è il .NET Framework 2.0.
L'errore in questo caso si riferiva all'attributo targetFramework presente sul web.config.
Per sistemarlo ho creato un nuovo "pool di applicazioni" sul menu di sinistra sopra la voce Siti


ovviamente modificando la versione del .NET Framework utilizzato (scegliere Integrata come modalità pipeline).

Quindi cliccando sul tasto destro del nostro sito accedere alla voce Gestisci sito Web/Impostazioni avanzate

e quindi impostare il pool di applicazioni corretto.

L'ultimo errore, questo davvero rognoso, lo ho avuto una volta risolti tutti i precedenti.
Praticamente dopo essermi autenticato avevo il messaggio:

Nell'elenco moduli del gestore "WebServiceHandlerFactory-Integrated" è presente un modulo "ManagedPipelineHandler" non valido


Spulciando alcuni forum ho visto che si tratta di un problema relativo all'installazione di asp.net.

Ho risolto lanciando da dos il seguente comando:

%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -i

e riavviando IIS











Java creare Url da Stringa



 private static URL getUrlFromWsdl(String wsdl) {
     URL baseUrl=null;
        try {
            baseUrl = new URL(wsdl);
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return baseUrl;
 }

Web Service Java con autenticazione BASIC

Utilizzando JAX-WS, per effettuare una chiamata ad un servizio web protetto con autenticazione BASIC occorre impostare il codice in questo modo:


Authenticator.setDefault(new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
      return new PasswordAuthentication(
        username,
       password.toCharArray());
    }
   });
   // WsTestService s=new WsTestService(urlWsdl);
        Service1 s=new Service1();
        
        Service1Soap ws=s.getService1Soap();
        BindingProvider prov=(BindingProvider)ws;
        prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
        prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);


Da notare che occorre anteporre l'authenticator perchè il client costruito con JAX-WS effettua una connessione tramite oggetto url prima di invocare le operazioni, quindi bisogna fornire prima i dati di autenticazione e poi dopo in fase di chiamata inserendole nel request context.

Mi è capitato di avere problemi con questo sistema su una installazione avvenuta in ambiente Windows Server 2008.
Ricevevo infatti errore di tipo 401 (Autenticazione non valida) e mettendo un TCP Monitor ho visto che nella richiesta effettuata la modalità di autorizzazione era NTLM invece di BASIC.
Quindi ho aggiunto prima dell'authenticator la seguente riga di codice:


System.setProperty("http.auth.preference", "basic");



mercoledì 9 ottobre 2013

Differenze conteggio caratteri tra javascript e java lato server

Con un formato testo libero (es. textarea) mi è capitato il seguente problema.
Il codice javascript lato client effettua un controllo sulla numerosità dei caratteri e lato server allo stesso modo si verifica di non eccedere la quota per evitare problemi sul db.
Il massimo impostabile è 1000 caratteri.
Solo che i due valori non collimano sempre.
In presenza di testi copiati e incollati da fonti esterne (siti di giornali etc.) succede che il frontend passa 1000 caratteri ma il back end se ne trova di più.
Indagando un pò il problema ho visto che è dovuto ai caratteri di  a capo, che nella request http sono identificati dallo /r.
Quindi ogni carattere di a capo mi viene a contare per 2.
Ho risolto inserendo una replace lato java, in questo modo:

x.replaceAll("\r", "");