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); }
java
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; } //...
@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.
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; } }
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.
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:
google / compile-testing
Pues no se que estaba haciendo o que articulo leía, al final llegue al código que tiene Google en GitHub. Me he encontrado con este proyecto, estaba de los primeros, no tengo tiempo para verlos todos (buaaa!!).
Y me ha encantado como programa esta gente. Que sencillo lo hacen. Este post esta aquí para que no se me olvide obtener el código y aprender de él.
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");
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>
- AGPL-3
- APACHE-2
- BSD-2
- BSD-3
- BSD-4
- GPL-3
- LGPL-3
- MIT
- MPL-2
- WTFPL
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.