addProxy

gist

	public static void addProxy(String user, String pass, String host, String port) {

		if(user!= null && pass != null) {
			final String authUser = user;
			final String authPassword = pass;

			Authenticator.setDefault(
					new Authenticator() {
						public PasswordAuthentication getPasswordAuthentication() {
							return new PasswordAuthentication(
									authUser, authPassword.toCharArray());
						}
					}
			);

			System.setProperty("http.proxyUser", authUser);
			System.setProperty("http.proxyPassword", authPassword);
		}

		System.setProperty("http.proxyHost", host);
		System.setProperty("http.proxyPort", port);
	}
addProxy

Reflection: Prohibited package name

Estaba invocando una clase para hacer reflexión sobre ella y llamar a un método especifico. Esta clase tenia un paquete que se denomina tal que asi:
java.xxx.yyy.clase.java

Y me salta en las pruebas un error tal que:

java.lang.SecurityException: Prohibited package name: java.xxx.yyy

Motivo: aquellos paquetes que empiezan por ‘java.‘ están “reservados”, es decir no se puede hacer reflexión sobre ellos pues en su código fuente así lo especifica. En la clase ClassLoader. Aquí el fragmento:

//...
private ProtectionDomain More preDefineClass(String name, ProtectionDomain protectionDomain) {
        if (!checkName(name))
            throw new NoClassDefFoundError("IllegalName: " + name);

        if ((name != null) && name.startsWith("java.")) {
            throw new SecurityException("Prohibited package name: " +
                                        name.substring(0, name.lastIndexOf('.')));
        }
        if (protectionDomain == null) {
            protectionDomain = getDefaultDomain();
        }

        if (name != null)
            checkCerts(name, protectionDomain.getCodeSource());

        return protectionDomain;
    }
//...
Reflection: Prohibited package name

@Transactional y @Rollback en Spring JDBC

Estoy en un proyecto en el que he abandonado Hibernate. Prefiero tener el control de las queries. Realmente no van a ser unas queries poderosas, pero tambien es cierto que realmente no entiendo la ventaja de Hibernate. Y para colmo no tengo acceso a ningun curso, con el cual pueda abrir los ojos.

He decidido probar Spring JDBC. Uso NamedParameterJdbcTemplate para todas las operaciones. Esto implica no tener que estar inyectando el DataSource por todos los lados. Simplificación y legibilidad.

Con el paso de los días, y en progresión a la experiencia. Decidí hacer test, pero sin grabar en bbdd. Haciendo rollback. Así me queda un proyecto tan completo como los que he realizado con Hibernate. Añadí a mi fichero de configuración de Spring:


    <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />

    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

y en los métodos en los que se hace insert, update ó delete, indico la anotación @Transactional

	@Transactional
	protected void update(String query, T bean) {
	      // ...
	}

Ahora bien, en los test. He estado probando y realizando pruebas para saber concretamente el uso que tiene Transactional y Rollback.

  • Si pones solo Transacctional , hara rollback, cuando se lance alguna excepción no cacheadas (derivadas de RuntimeException). Dentro de la anotación puedes indicarle otras opciones.
  • Si acompañas la anotacion @Transacctional con @Rollback (por defecto es true), estas indicando que siempre se va a hacer Rollback. Mediante la anotacion Rollback, estas sobreescribiendo el comportamiento de Transacctional, referente a los rollback.
  • 	@Test
    	@Transactional
    	@Rollback
    	public void testSave() {
    	      // ...
    	}
    

    Indicar @Transacctional en el metodo de test, es sobreescribir el comportamiento de @Transacctional en el metodo a testear.

El Javadoc de Rollback dice:

Test annotation to indicate whether or not the transaction for the annotated
test method should be rolled back after the test method has
completed. If {@code true}, the transaction will be rolled back;
otherwise, the transaction will be committed.

@Transactional y @Rollback en Spring JDBC

Semaforos en Java

Me había construido una clase que era un semáforo de procesos. Cuando me he preguntado, lo que suelo preguntarme: “¿y esto, no lo habrá hecho otro ya?”. Y la respuesta es si, existen desde hace ni se sabe .

java.util.concurrent.Semaphore

y se pueden instanciar desde Spring.

	<bean id="semaphoreJobA" class="java.util.concurrent.Semaphore">
		<constructor-arg index="0" type="int" value="1" />
		<constructor-arg index="1" type="boolean" value="true" />
		<!-- permits - the initial number of permits available. This value may 
			be negative, in which case releases must occur before any acquires will be 
			granted. -->
		<!-- fair - true if this semaphore will guarantee first-in first-out granting 
			of permits under contention, else false -->
	</bean>

Luego en tu clase, los invocas y les dejas hacer su magia.

	@Override
	public void execute(JobExecutionContext context)
			throws JobExecutionException {

		// Invoco a Spring, por que estoy ejecutando fuera de su contexto.
		Semaphore semaphoreJobA = (Semaphore) SpringApplicationContext.getBean("semaphoreJobA");
		String whoiam = String.valueOf(this.hashCode());
		try{
			LOGGER.info("t"+whoiam +"-"+ taskType.name()+"t Pregunto al semaforo si puedo continuar");
			semaphoreJobA.acquire();
			LOGGER.info("t"+whoiam +"-"+ taskType.name()+"t He pasado, ejecutando tarea...");
			doTask(whoiam);
		}catch(Exception e){
			LOGGER.error("t"+whoiam +"-"+ taskType.name()+"t Error: ", e);
			
			JobExecutionException e2 = new JobExecutionException(e);
			e2.setStackTrace(e.getStackTrace());
			throw e2;			
		}finally{
			semaphoreJobA.release();
		}

	}

¿Como era mi clase?, ya probada y testeada. Con muchas mejoras por hacer…

package net.pp.jm.scheduler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Cualquiera puede coger la vez no importa el orden de llegada sino el mas rapido en cuanto este vacio el semaforo
 * 
 * @author josemanuel.prietopalacios.net
 *
 */
public class Semaforo {

	private static final Logger LOGGER = LoggerFactory.getLogger(Semaforo.class);

	// estos podrian ser semaforos del API Java...
	int hashCodeTask1;
	int hashCodeTask2;
	int hashCodeTask3;
	int hashCodeTask4;

	private boolean finish_method_run;

	public synchronized boolean running(TaskType tarea, int hashCode){
		LOGGER.info(hashCode +"-"+ tarea.name() + " solicitud de ejecucion");

		// Aqui se puede usar un Lock: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html
		if(finish_method_run){
			while(!finish_method_run){
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					LOGGER.error("ERROR: ", e);
				}
			}
		}
		
		if(ican(tarea, hashCode)){
			switch(tarea){
			case tarea1: hashCodeTask1 = hashCode; break;
			case tarea2: hashCodeTask2 = hashCode; break;
			case tarea3: hashCodeTask3 = hashCode; break;
			case tarea4: hashCodeTask4 = hashCode; break;
			}
			LOGGER.info(hashCode +"-"+ tarea.name() + " running...");
			return true;
		}else{
			return false;
		}
	}

	private boolean ican(TaskType tarea, int hashCode){
		boolean ican = false;
		switch(tarea){
		case tarea1: ican = (hashCodeTask1 != 0) ? false : true; break;
		case tarea2: ican = (hashCodeTask2 != 0) ? false : true; break;
		case tarea3: ican = (hashCodeTask3 != 0) ? false : true; break;
		case tarea4: ican = (hashCodeTask4 != 0) ? false : true; break;
		}
		return ican;
	}

	public synchronized void finish(TaskType tarea, int hashCode){
		finish_method_run = true;
		switch(tarea){
		case tarea1: hashCodeTask1 = 0; break;
		case tarea2: hashCodeTask2 = 0; break;
		case tarea3: hashCodeTask3 = 0; break;
		case tarea4: hashCodeTask4 = 0; break;
		}
		LOGGER.info(hashCode +"-"+ tarea.name() + " finish");
		finish_method_run = false;
	}

}
Semaforos en Java

listar librerias java del servidor

Con este comando listamos todas las librerias del servidor y quitamos la ruta, nos quedamos solo con el nombre del jar.

locate *.jar | sed 's/// /g' | sed '/[a-z]*.jar$/ s/[a-z]* //g' | sort

comando locate *.jar : busca todos los ficheros que acaben por .jar
comando sed ‘s/// /g’ : elimina la barra y la sustituye por ‘ ‘(espacio en blanco).
comando sed ‘/[a-z]*.jar$/ s/[a-z]* //g’ : de todas las lineas que cumplan el patrón (la linea termina por .jar) elimina cualquier elemento que contemple el patron (letras seguidas de un espacio). Es decir, elimino la ruta de los ficheros.

listar librerias java del servidor

Java UNICODE

Recientemente el eclipse ha dejado de convertir de UTF-8 a unicode mis properties de i18n. En lugar de intentar arreglarlo (acierto), me he puesto a configurar los acentos y eñes en los distintos lenguajes con los que trabajamos, a mano (error).

Aquí esta la tabla con los caracteres específicos del castellano.

Como no tengo tiempo a mas, aquí pongo unos blogs y tutoriales sobre como maneja Java el UNICODE:

Java UNICODE

Enviar PDF Base64 y recibirlo

No convertir a String en ningun momento.

package net.pp.jm.varios;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;

import es.depontevedra.portales.portlets.facturae.util.ConstFacturae;

public class VariousTest {

	public static void main(String[] args) throws Exception {
		FileInputStream fis = new FileInputStream("c:\p.pdf");
		byte[] bb = IOUtils.toByteArray(fis);
		IOUtils.closeQuietly(fis);
		
		// lo envia el WS - el cliente lo recibe
		String fileB64 = Base64.encodeBase64String(bb);

		byte[] bb2 = Base64.decodeBase64(fileB64);
		
		FileOutputStream fos = new FileOutputStream("c:\p2_byte.pdf");
		IOUtils.write(bb2, fos);
		IOUtils.closeQuietly(fos);
	
		System.out.println("DONE");
	}
}

En mi caso tenia el problema que estaba recibiendo el Base64 y este habia sido codificado. Probando codificaciones di con la buena.

		String fileB64 = Base64.encodeBase64String(bb);
		byte[] utf8 = Base64.decodeBase64(fileB64);	
		byte[] latin1 = new String(utf8, "UTF-8").getBytes("ISO-8859-1");

		FileOutputStream fos = new FileOutputStream("c:\p2_byte.pdf");
		IOUtils.write(bb2, fos);
		IOUtils.closeQuietly(fos);
		System.out.println("DONE");
Enviar PDF Base64 y recibirlo

Add license to Java source Maven project

from this project.

	<build>
		<plugins>
			<plugin>
				<groupId>com.mycila</groupId>
				<artifactId>license-maven-plugin</artifactId>
				<version>2.6</version>
				<configuration>
					<header>com/mycila/maven/plugin/license/templates/APACHE-2.txt</header>
					<properties>
						<owner>Jose Manuel Prieto Palacios</owner>
						<email>josemanuel@prietopalacios.net</email>
					</properties>
					<excludes>
						<exclude>**/README</exclude>
						<exclude>**/*.launch</exclude>
						<exclude>**/*.xml</exclude>
						<exclude>**/*.properties</exclude>
						<exclude>**/*.txt</exclude>
						<exclude>src/test/resources/**</exclude>
						<exclude>src/main/resources/**</exclude>
					</excludes>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>check</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>

Licenses:

  • AGPL-3
  • APACHE-2
  • BSD-2
  • BSD-3
  • BSD-4
  • GPL-3
  • LGPL-3
  • MIT
  • MPL-2
  • WTFPL
Add license to Java source Maven project

Apache RAT

Apache RAT, pertenece al proyecto Apache Creadur. Por lo poco que he entendido, es para agregar licencias a todas tus clases, ficheros. Tal y como esta cualquier clase de Apache, donde aparece arriba del todo, despues de la palabra reservada package, la licencia.
Pero para salir de dudas, me he descargado la libreria y he realizado estas pruebas.

Dentro de la carpeta descomprimida, he creado la carpeta “test”. En esta carpeta he metido una clase, que ha resultado ser una interfaz de un web service.
Ubicado en la carpeta descomprimida he ejecutado lo siguiente:

 
E01740@ES-D-04744LT /cygdrive/c/Software/apache-rat-0.10
$ java -jar apache-rat-0.10.jar --help
usage: java rat.report [options] [DIR|TARBALL]
Options
 -A,--addLicense                Add the default licence header to any file
                                with an unknown licence that is not in the
                                exclusion list. By default new files will
                                be created with the licence header, to
                                force the modification of existing files
                                use the --force option.
 -a,--addLicence                Add the default licence header to any file
                                with an unknown licence that is not in the
                                exclusion list. By default new files will
                                be created with the licence header, to
                                force the modification of existing files
                                use the --force option.
 -c,--copyright <arg>           The copyright message to use in the
                                licence headers, usually in the form of
                                "Copyright 2008 Foo"
 -d,--dir                       Used to indicate source when using
                                --exclude
 -E,--exclude-file <fileName>   Excludes files matching regular expression
                                in <file> Note that --dir is required when
                                using this parameter.
 -e,--exclude <expression>      Excludes files matching wildcard
                                <expression>. Note that --dir is required
                                when using this parameter. Allows multiple
                                arguments.
 -f,--force                     Forces any changes in files to be written
                                directly to the source files (i.e. new
                                files are not created)
 -h,--help                      Print help for the Rat command line
                                interface and exit
 -s,--stylesheet <arg>          XSLT stylesheet to use when creating the
                                report.  Not compatible with -x
 -x,--xml                       Output the report in raw XML format.  Not
                                compatible with -s

NOTE:
Rat is really little more than a grep ATM
Rat is also rather memory hungry ATM
Rat is very basic ATM
Rat highlights possible issues
Rat reports require intepretation
Rat often requires some tuning before it runs well against a project
Rat relies on heuristics: it may miss issues

Asi que si no lo he entendido mal. Si ejecuto esto:

 
$ java -jar apache-rat-0.10.jar -d test -a

*****************************************************
Summary
-------
Generated at: 2014-04-30T09:39:43+02:00
Notes: 0
Binaries: 0
Archives: 0
Standards: 1

Apache Licensed: 0
Generated Documents: 0

JavaDocs are generated and so license header is optional
Generated files do not required license headers

1 Unknown Licenses

*******************************

Unapproved licenses:

  test/Cargos.java

*******************************

Archives:

*****************************************************
  Files with Apache License headers will be marked AL
  Binary files (which do not require AL headers) will be marked B
  Compressed archives will be marked A
  Notices, licenses etc will be marked N
 !????? test/Cargos.java

*****************************************************
 Printing headers for files without AL header...


=======================================================================
==test/Cargos.java
=======================================================================
package es.depontevedra.soap.cargows.services;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.BindingType;

@WebService
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface Cargos {

        @WebMethod(action="crearCargo")
        public String crearCargo(String xml);

        @WebMethod(action="modificarCargo")
        public String modificarCargo(String xml);

        @WebMethod(action="anularCargo")
        public String anularCargo(String xml);

        @WebMethod(action="consultarCargo")
        public String consultarCargo(String xml);

        @WebMethod(action="consultarConceptos")
        public String consultarConceptos(String xml);

        @WebMethod(action="consultarTributos")
        public String consultarTributos(String xml);

        @WebMethod(action="obtenerRecibo")
        public String obtenerRecibo(String xml);

}

Parece que ha tocado algo en mi clase. La reviso:

 
package es.depontevedra.soap.cargows.services;
/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.BindingType;

@WebService
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface Cargos {

	@WebMethod(action="crearCargo")
	public String crearCargo(String xml);
	
	@WebMethod(action="modificarCargo")
	public String modificarCargo(String xml);
	
	@WebMethod(action="anularCargo")
	public String anularCargo(String xml);
	
	@WebMethod(action="consultarCargo")
	public String consultarCargo(String xml);
	
	@WebMethod(action="consultarConceptos")
	public String consultarConceptos(String xml);
	
	@WebMethod(action="consultarTributos")
	public String consultarTributos(String xml);
	
	@WebMethod(action="obtenerRecibo")
	public String obtenerRecibo(String xml);
	
}

Me ha gustado eso del copyright que aparece en la ayuda. Voy a probar:

 
$ java -jar apache-rat-0.10.jar -d test -a -c "Jose Manuel Prieto Palacios"

Mi clase se queda:

 
package es.depontevedra.soap.cargows.services;
/*
 *
 * Jose Manuel Prieto Palacios
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.BindingType;

@WebService
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface Cargos {

	@WebMethod(action="crearCargo")
	public String crearCargo(String xml);
	
	@WebMethod(action="modificarCargo")
	public String modificarCargo(String xml);
	
	@WebMethod(action="anularCargo")
	public String anularCargo(String xml);
	
	@WebMethod(action="consultarCargo")
	public String consultarCargo(String xml);
	
	@WebMethod(action="consultarConceptos")
	public String consultarConceptos(String xml);
	
	@WebMethod(action="consultarTributos")
	public String consultarTributos(String xml);
	
	@WebMethod(action="obtenerRecibo")
	public String obtenerRecibo(String xml);
	
}

Configurarlo con maven

Uso basico
En la fase de verificacion
Añadiendo un informe cuando el proyecto se compila
Aplicar una licencia personalizada

En maven simplemente se comprueba que todos los ficheros tienen licencia. Usar solo como verificador.

Apache RAT