martes, 12 de diciembre de 2017

La API de JPA 2.1 (V) Programaticamente actualizar la conexion a la BD

Se pueden crear persistence units programaticamente en estas condiciones:

  1. Utilizando Spring (ver stack overflow)
  2. Utilizando Hibernate (ver el mismo link en  stack overflow)
  3. Implementando la interface PersistenceProvider (ver el mismo link en stack overflow y JPA API

  • En principio voy a descartar Spring pues mete muchas jars que no necesitamos.
  • También voy a descartar usar Hibernate cuando se desmarca de la JPA API
  • El tercer método parece un poco laborioso ya que hay que implementar la interface PersistenceProvider.
Lo que he pensado, es tener una persistence unit (o varias) definidas en el persistencel.xml y modificar la conexión a la BD.

Para ello podemos tener un persistence.xml como este


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    
        <persistence-unit name="sqlserver-jtds" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

          <properties>
            <!-- Configuring JDBC properties -->
            <!-- -->
            <!-- -->
            
             
            <property name="javax.persistence.jdbc.url" value="jdbc:jtds:sqlserver://111.111.11.11:1433/DB2017" /> 
            <property name="javax.persistence.jdbc.user" value="myuser" />
            <property name="javax.persistence.jdbc.password" value="mypassword" />
            <property name="javax.persistence.jdbc.driver" value="net.sourceforge.jtds.jdbc.Driver" />

            <!-- Hibernate properties -->
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2008Dialect" />
            <property name="hibernate.hbm2ddl.auto" value="none" />  <!-- update -->

            <!-- Configuring Connection Pool -->
            <property name="hibernate.c3p0.min_size" value="5" />
            <property name="hibernate.c3p0.max_size" value="20" />
            <property name="hibernate.c3p0.timeout" value="500" />
            <property name="hibernate.c3p0.max_statements" value="50" />
            <property name="hibernate.c3p0.idle_test_period" value="2000" />
          </properties>
    </persistence-unit>  
          
</persistence>

la idea es seleccionar esta persistence unit "sqlserver-jtds" y cambiarle la propieded "javax-persistence.jdbc.url" a "jdbc:jtds:sqlserver://111.111.11.11:1433/DB2018".

Para ello, basandonos en stack overflow ejecutamos este código java:


1
2
3
Properties props = new Properties();
props.setProperty("javax.persistence.jdbc.url", "jdbc:jtds:sqlserver://111.111.11.11:1433/DB2018");
EntityManagerFactory emf=javax.persistence.Persistence.createEntityManagerFactory("sqlserver-jtds", props);

Con lo que hemos aprovechado el persistence.xml que había y le hemos cambiado la conexión programáticamente.

Esto viene bien cuando se cambia de año y hay que trabajar en otra base de datos correspondiente a ese año. Para ello se puede utilizar un fichero de propiedades para guardar el nombre de la BD.

En fin chapucillas que vienen bien y no complican el código.


lunes, 27 de noviembre de 2017

La API de JPA 2.1 (IV) Utilizando funciones de la BBDD con JPA 2.1

Cuando se plantea una migración de datos, resulta importante poder utilizar funciones de la Base de Datos.  Estas funciones nos ahorran un montón de cálculos, y na vez definidas se pueden reutilizar.


Aquí os dejo 2 enlaces donde se pueden usar las funciones definidas en las base de datos sin tener que utilizar Native Querys

1. Stackoverflow (answer of Bunti)
2. Thoughts on Java de Thorben Janssen

viernes, 24 de noviembre de 2017

Crear jar ejecutable con Maven que incluya recursos. Los jars en librerias a parte

Actualización a 27/12/2017


Tenía un proyecto eclipse normal sin web, al que modifiqué unas tonterias de una clase ejecutable. Cuando generé el jar ejecutable, éste corría bien en mi ordenador pero había otros que no corría. dándole vueltas al asunto averigüé que Eclipse Mars y Java 1.8 no eran completatamente compatibles cuando se genera un jar ejecutable. La solución ha sido copiar el proyecto a un Eclipse Oxygen y generar el jar. Y ya va a pesar que se tienen que ejecutar en un entorno

=====================================================================

Mira que me llevo todo el día dándole vueltas al asunto. Quiero hacer un programa que se ejecute cada cierto tiempo para realizar actualizaciones periódicas. Para ello dispongo de un servidor virtual que va a realizar dichas tareas.

Hacer un jar ejecutable es fácil basta en Eclipse hacer  File-Export-Java-Runnable JAR File (se selecciona Package Required libraries into generatd JAR). Pero, si estamos trabajando con Maven, y utilizamos la carpeta src/main/resources para guadar propiedades, persitence.xml etc... la cosa cambia.

La solución más acertada que he encontrado ha sido la de Crunchify . Por desgracia o por suerte las dependencias (jars)  que se definen en el pom.xml se guardan en la carpeta lib.

Veamos primeramente el fichero pom.xml

CODIGO DE JAVA 9


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>WSRegJPAFac01</groupId>
  <artifactId>WSRegJPAFac01</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>
  <name>WSRegJPAFac01</name>
  <description>WS resgistre factures Aytos</description>
  
  <!-- New repository for JAX implementation not included in jdk 9 -->
  <!-- See https://stackoverflow.com/questions/15429142/add-maven-repositories-for-a-project-in-eclipse-->
  <!-- http://openjdk.java.net/jeps/320 -->
  <!--  repositories>
    <repository>
        <id>maven-central-repo1</id>
        <name>Central repository</name>
        <url>http://repo1.maven.org/maven2</url>
    </repository>
  </repositories-->
  
  <properties>
    <cxf.version>3.2.1</cxf.version>
    <jax.version>2.3.0</jax.version>
    <failOnMissingWebXml>false</failOnMissingWebXml>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- Java version-->
    <java.version>9</java.version>
  </properties>  
  
  


  
  <dependencies>
  
    <!-- WS DEPENDENCIES -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxws</artifactId>
        <version>${cxf.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>${cxf.version}</version>
    </dependency>
        <!-- Jetty is needed if you're are not using the CXFServlet -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http-jetty</artifactId>
        <version>${cxf.version}</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.18</version>
      <scope>provided</scope>
    </dependency>
    <!-- END WS DEPENDENCIES -->
    
    
    <!-- JPA & SQL SERVER DEPENDENCIES-->
    <!-- JPA & Postgres -->
    <!-- Javassist required by Hibernate in some computers -->
    <!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
    <dependency>
      <groupId>org.javassist</groupId>
      <artifactId>javassist</artifactId>
      <version>3.22.0-GA</version>
    </dependency>
    
    <!-- JPA 2.1 Provider -->
    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.2.12.Final</version>
    </dependency>
    
    <!-- MS-SQL Server JDBC driver de microsoft = KK-->
    <!-- https://mvnrepository.com/artifact/com.microsoft.sqlserver/mssql-jdbc -->
    <dependency>
      <groupId>com.microsoft.sqlserver</groupId>
      <artifactId>mssql-jdbc</artifactId>
      <version>6.2.2.jre8</version>
      <scope>test</scope>
    </dependency>
    
    <!-- MS-SQL Server JDBC JTDS bo de 2013-->
    <!-- https://mvnrepository.com/artifact/net.sourceforge.jtds/jtds -->
    <dependency>
      <groupId>net.sourceforge.jtds</groupId>
      <artifactId>jtds</artifactId>
      <version>1.3.1</version>
    </dependency>
    
    <!--  Apache commons string utils .. -->
    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.7</version>
    </dependency>
    
    <!--BEGIN Java 9 references to JEE  not included in JDK9-->
    <!-- see http://openjdk.java.net/jeps/320-->
    
    <!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
    <!--dependency>
      <groupId>javax.xml.bind</groupId>
      <artifactId>jaxb-api</artifactId>
      <version>${jax.version}</version>
    </dependency-->
    
    <!-- https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-impl -->
    <!-- dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-impl</artifactId>
      <version>${jax.version}</version>
    </dependency-->
        
    <!-- https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-core -->
    <!-- dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-core</artifactId>
      <version>${jax.version}</version>
    </dependency-->
    
    <!-- https://mvnrepository.com/artifact/javax.activation/javax.activation-api -->
    <!-- dependency>
      <groupId>javax.activation</groupId>
      <artifactId>javax.activation-api</artifactId>
      <version>1.2.0</version>
    </dependency-->
    
    <dependency>
      <groupId>com.sun.activation</groupId>
      <artifactId>javax.activation</artifactId>
      <version>1.2.0</version>
    </dependency>
    
    <dependency>
      <groupId>com.sun.xml.ws</groupId>
      <artifactId>jaxws-ri</artifactId>
      <version>${jax.version}</version>
      <type>pom</type>
    </dependency>
    
    <dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-ri</artifactId>
      <version>${jax.version}</version>
      <type>pom</type>
    </dependency>
    
    <dependency>
      <groupId>javax.transaction</groupId>
      <artifactId>javax.transaction-api</artifactId>
      <version>1.2</version>
    </dependency>
    
     <dependency>
      <groupId>javax.annotation</groupId>
      <artifactId>javax.annotation-api</artifactId>
      <version>1.2</version>
    </dependency>
    
       
    <!-- dependency>
      <groupId>javax.annotation</groupId>
      <artifactId>javax.annotation-api</artifactId>
      <version>1.3.1</version>
    </dependency-->

    <!-- End of Dependencies required for JAVA 9!!!! -->
    
    
    
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    
    <!-- END JPA & SQL SERVER DEPENDENCIES -->
    
    
    
    
  </dependencies>


<!-- Esta si que va bien  http://crunchify.com/how-to-create-build-java-project-including-all-dependencies-using-maven-maven-resources-maven-dependency-maven-jar-plugin-tutorial/
  -->
  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.7.0</version>
          <configuration>
            <source>${java.version}</source>
            <target>${java.version}</target>
            <showWarnings>true</showWarnings>
            <showDeprecation>true</showDeprecation>
            <!-- fork compilation and use the
       specified executable -->
   <!--
    <fork>true</fork>
    <executable>javac9</executable>
   --> 
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
 
    <plugins>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.0.2</version>
        <executions>
          <execution>
            <id>copy-resources</id>
            <phase>validate</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>${basedir}/target/MiCarpeta</outputDirectory>
              <resources>
                <resource>
                  <directory>resources</directory>
                  <filtering>true</filtering>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
 
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>3.0.2</version>
        <executions>
          <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}/MiCarpeta/lib</outputDirectory>
              <overWriteReleases>false</overWriteReleases>
              <overWriteSnapshots>false</overWriteSnapshots>
              <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
          </execution>
        </executions>
      </plugin>
   
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.0.2</version>
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
              <classpathPrefix>lib/</classpathPrefix>
              <mainClass>ximodante.aytos.operation.AytosOperationUtil</mainClass>
            </manifest>
            <manifestEntries>
              <Class-Path>.</Class-Path>
            </manifestEntries>
          </archive>
 
          <finalName>MiCarpeta/MiJar</finalName>
        </configuration>
      </plugin>
    </plugins>
  
  </build>


</project>


CODIGO DE JAVA 1.8

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  
  <modelVersion>4.0.0</modelVersion>
  <groupId>WSRegJPAFac</groupId>
  <artifactId>WSRegJPAFac</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>WSRegJPAFac</name>
  <packaging>jar</packaging>
  <description>Registre Factures Teralco des de Aytos FAC</description>
  

  <properties>
    <cxf.version>3.2.0</cxf.version>
    <failOnMissingWebXml>false</failOnMissingWebXml>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    
  </properties>  
  
  


  
  <dependencies>
  
    <!-- WS DEPENDENCIES -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxws</artifactId>
        <version>${cxf.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>${cxf.version}</version>
    </dependency>
        <!-- Jetty is needed if you're are not using the CXFServlet -->
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http-jetty</artifactId>
        <version>${cxf.version}</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.18</version>
      <scope>provided</scope>
    </dependency>
    <!-- END WS DEPENDENCIES -->
    
    <!-- JPA & SQL SERVER DEPENDENCIES-->
    <!-- JPA 2.1 Provider -->
    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.2.12.Final</version>
    </dependency>
    
    <!-- MS-SQL Server JDBC driver de microsoft = KK-->
    <!-- https://mvnrepository.com/artifact/com.microsoft.sqlserver/mssql-jdbc -->
    <dependency>
      <groupId>com.microsoft.sqlserver</groupId>
      <artifactId>mssql-jdbc</artifactId>
      <version>6.2.2.jre8</version>
      <scope>test</scope>
    </dependency>
    
    <!-- MS-SQL Server JDBC JTDS bo de 2013-->
    <!-- https://mvnrepository.com/artifact/net.sourceforge.jtds/jtds -->
    <dependency>
      <groupId>net.sourceforge.jtds</groupId>
      <artifactId>jtds</artifactId>
      <version>1.3.1</version>
    </dependency>
    
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <!-- END JPA & SQL SERVER DEPENDENCIES -->
    
    
    
</dependencies>


<!-- Esta si que va bien  http://crunchify.com/how-to-create-build-java-project-including-all-dependencies-using-maven-maven-resources-maven-dependency-maven-jar-plugin-tutorial/
  -->
  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.7.0</version>
          <configuration>
            <source>1.8</source>
            <target>1.8</target>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
 
    <plugins>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.0.2</version>
        <executions>
          <execution>
            <id>copy-resources</id>
            <phase>validate</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>${basedir}/target/MiCarpeta</outputDirectory>
              <resources>
                <resource>
                  <directory>resources</directory>
                  <filtering>true</filtering>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
 
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}/MiCarpeta/lib</outputDirectory>
              <overWriteReleases>false</overWriteReleases>
              <overWriteSnapshots>false</overWriteSnapshots>
              <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
          </execution>
        </executions>
      </plugin>
   
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
              <classpathPrefix>lib/</classpathPrefix>
              <mainClass>ximodante.aytos.operation.AytosOperationUtil</mainClass>
            </manifest>
            <manifestEntries>
              <Class-Path>.</Class-Path>
            </manifestEntries>
          </archive>
 
          <finalName>MiCarpeta/MiJar</finalName>
        </configuration>
      </plugin>
    </plugins>
  
  </build>


</project>


Tenemos que centrarnos en la última parte  (que tiene fondo azul claro)y sobre todo en los parámetros que están en rojo. Esta parte comprende los plugins necerarios para generar el jar. Siendo:

jar: Es el formato a generar (línea 9)
MiCarpeta: Es la carpeta que cuelga de target donde se generará el jar. (linea 91)
ximodante.aytos.operation.AytosOperationUtil es la clase que tiene el main a ejecutar (linea 170)
MiCarpeta/lib: es donde se guardarán los diferentes jars de las librerías referenciadas. (linea 154)
MiJar: Es el nombre propuesto al fichero jar a generar (MiJar.jar) (linea 178)

Destacar la dependencia javassist que en algunas máquinas la pide Hibernate y en otras no! Por tanto es importante indicarla para no tener sorpresas.

Para obtener el jar hacemos click derecho sobre el proyecto- Run AS- 4 Maven Build y seleccionamos clean install en el apartado goals como se indica en la imagen.





Ahora solo queda copiar la carpeta MiCarpeta (que está dentro de target)  a un equipo que tenga instalada una versión reciente de java y a funcionar.


Happy coding!

NOTA: Con java 9 tenemos algunas pequeñas diferencias y además se queja de Lombok:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by lombok.javac.apt.LombokProcessor to field com.sun.tools.javac.processing.JavacProcessingEnvironment.discoveredProcs
WARNING: Please consider reporting this to the maintainers of lombok.javac.apt.LombokProcessor
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
[


martes, 7 de noviembre de 2017

Informatica Jurásica (I). Windows XP, VB 6.0 , MSDN

0. Introducción


Me he visto en la necesidad de tocar el código fuente de una antigua aplicación funcional hecha en VB6.0, pero actualmente tengo una máquina Ubuntu. Para ello he hecho el siguiente planning.



  1. Instalar Oracle Virtual Box y algunos de sus complementos.
  2. Instalar Windows XP con el Service Pack 3s
  3. Instalar Microsoft VB 6.0 que estaba en Visual Studio 6.0
  4. Instalar el Service Pack 6 del Visual Studio.
  5. Cargar el proyecto y ... sorpresa, re-referenciar los Microsoft ActiveX Data Objects de la v.2.5 a la v.2.8 y a funcionar.

1. Virtual Box


Se descarga e instala (haciendo doble click se instala en Ubuntu) 
Una vez instalado, también se puede instalar el Extensión Pack para que reconozca los USB 2.0 y 3.0

Se crea una maquina nueva dentro de V.Box tipo XP 32 bits. y se descarga el Virtual Box Gest Additions image (en iso). Se le asigna el CD la esta iso de Guest additions y a instalar.


2. Instalar XP, VB, MSDN etc

Se busca una ISO del XP con SP3 y se la asocia al CD de la máquina y a instalar.
A continuacion se instala el Visual Studio 6.0 asignanado las ISOs al CD cada vez.
Se instala el MSDN, el Service Pack 6 de Visual Studio, que tenga los Microsoft ActiveX Data Objects 2.8 !!!!!

3. Cargar un proyecto

Verificar que el proyecto haga referencia a las Microsoft  ActiveX Data Objects 2.8 y no a la 2.5. y a funcionar.


4. CUIDADO!!!!

No se que pasa pero al exportar las imagenes en una máquina e importarlas en otra pueden fallar!!!!!!

viernes, 19 de mayo de 2017

Angular 2 y C3.css (3): Definición de componentes visuales primarios

Introducción

Queremos crear 3 componentes:

1. Componente principal AppComponent que es el contenedor de todo con el boton "hamberger" que oculta y muestra el menu lateral
2. Menu Lateral Izquierdo (Sidebar): SidebarComponent
3. Caja de contenidos en la parte derecha:ContentComponent

1. AppComponent

Veamos el código type script (app.component.ts)

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  title = 'app works!';
  sbVisible = false; // whether sidebar menu is visible or not

  // Hide or show sidebar
  hideSBOnOff(): void {
    this.sbVisible = !this.sbVisible;
  }
}

De este código destacamos:

1. La variable sbVisible que es la que indoca si el menú de la barra lateral esta visible (display:in-line) o si está oculto (display:none).

2. La función hideSBOnOff() lo que hace es cambiar el valor de sbVisible



Vemos el código html (app.component.html)

<div class="w3-main" id="main">

  <div class="w3-row w3-teal w3-border" id ="main-row">
    <div class="w3-container w3-col" style="width:100px">
      <button class="w3-button w3-xxlarge" (click)="hideSBOnOff()">&#9776;</button>
    </div>
    <div class="w3-container w3-rest">
      <h1>My Application</h1> 
    </div>
  </div><!--  end main-row-->
  

  <!--  Left for sidebar -->
  <app-sidebar [visible]="sbVisible"></app-sidebar>

  <!--  Right for content -->
  <app-content [sBarVisible]="sbVisible"></app-content>

</div> <!-- end main -->

De este código destacamos:

1. La creación de caracter "hamberguer" con &#9776;

2. Como llamamos a la función hideSBOnOff() al hacer click del boton: (click)="hideSBOnOff()"

3. Como insertamos los componentes AppSidebar y AppContent con las directivas <app-sidebar> y <app-content>

4. Como pasamos la variable sbVisible a cada componente, dentro de sus directivas correspondientes. Para ello, cada componente debe tener un atributo con la anotacion @Input que para el AppSidebar será el atributo "visible" y para el AppContent será "sBarVisible". Los atributos de cada componente iran entre corchetes [].

2. SidebarComponent

El código typescript es (sidebar.component.ts)

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-sidebar',
  templateUrl: './sidebar.component.html',
  styleUrls: ['./sidebar.component.css']
})

export class SidebarComponent implements OnInit {
  // whether is visible or not this component
  @Input() visible: boolean; // receives input from parent

  constructor() { }

  ngOnInit() {
  }

 // Gets the style and show or hide this sidebar
 getSideBarStyle() {
    const SideBarStyle = {
       'width': '25%',
       'display': this.visible ? 'inline-block' : 'none',
    };
    return SideBarStyle;
  }
}

Destacamos:

1. selector: 'app-sidebar' que es la directiva que utiliza el componente padre (appComponent) para incrustar este componente dentro del html del componente padre.

2. @Input() visible que es el atributo que le pasa el componente padre para que esté visible o no.

3. getSideBarStyle(): Que es la función que nos devuelve el estilo en función de si es visible o no. También nos da la anchura.

Veamos el codigo html (sidebar.component.html)

<div class="w3-sidebar w3-bar-block w3-card-2 w3-animate-left"  [ngStyle]="getSideBarStyle()" id="mySidebar">
  <!-- button class="w3-bar-item w3-button w3-large" (click)="hideOnOff()">Close &times;</button -->
  <a href="#" class="w3-bar-item w3-button">Link 1</a>
  <a href="#" class="w3-bar-item w3-button">Link 2</a>
  <a href="#" class="w3-bar-item w3-button">Link 3</a>

</div>


Destacamos como con la notación [ngStyle]="getSideBarStyle()" le asignamos el valor del estilo para que sea visible (display:in-line) o no (display:none).



3. ContentComponent

Veamos el código typescript:

import { Component, OnInit, Input, Output } from '@angular/core';

@Component({
  selector: 'app-content',
  templateUrl: './content.component.html',
  styleUrls: ['./content.component.css']
})
export class ContentComponent implements OnInit {
  @Input() sBarVisible: boolean; // <-- added Input annotation

  constructor() {
    this.sBarVisibleEmitter = new EventEmitter();
  }

  ngOnInit() {
  }

  // gets this componet style
  getContentStyle() {
    const mainStyle = {
       'margin-left': this.sBarVisible ? '25%' : '0%',
    };
    return mainStyle;
  }
}


Destacar:
1. selector: 'app-content' que es la directiva que usa el componente padre en el html para incluirlo
2. @Input sBarVisible que es la variable que le pasa el componente padre para decirle que la barra lateral esta visible o no para que este componente se readapte
3. getContentStyle() que es la función que cambia el estilo para que se comparta el contenido total con el menu lateral. Es este caso cuando la barra lateral es visible le damos un margen izquierdo del 25%

Veamos el html (content.component.html)

<div class="w3-tile" [ngStyle]="getContentStyle()" id="content">

  <img src="../assets/images/img_car.jpg" alt="Car" style="width:100%">

  <div class="w3-container">
    <p>In this example, the sidebar is hidden (style="display:none")</p>
    <p>It is shown when you click on the menu icon in the top left corner.</p>
    <p>When it is opened, it shifts the page content to the right.</p>
    <p>We use JavaScript to add a 25% left margin to the div element with id="main" when this happens. The value "25%" matches the width of the sidebar.</p>
  </div>

</div>

A destacar:

1. La aplicación de estilos con la directiva ngStyle: [ngStyle]="getContentStyle()" que utiliza la función getContentStyle del componente.

2. El resto de contenido es copiado de la web de w3schools. Observar que la foto del coche se ha puesto en el directorio assets/images

Pero no debemos olvidar el app.module.ts que es el que nos une todos los componentes:

3. AppModule.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { SidebarComponent } from './my_ui/sidebar/sidebar.component';
import { ContentComponent } from './my_ui/content/content.component';

@NgModule({
  declarations: [
    AppComponent,
    SidebarComponent,
    ContentComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Observar que cada componente lo crea en una carpeta nueva. Y también he creado la carpeta my_ui para saber tener todo junto esta parte de interfaz de usuario (my_ui)

Si ejecutamos queda esto:

Y si mostramos el menu lateral dandole al boton hamberguer:




4. Conclusiones

De momento no hemos utilizado el modelado de datos. En esta tercera entrega solo hemos comprobado que los componentes hacen lo que queremos.

Angular 2 y C3.css (2): Definición del modelo de datos

Introducción

Primeramente vamos a definir el modelado de los elementos de la interfaz de usuario

1. Modelo de datos

En principio crearemos varios ficheros: 
  • config.model.ts: donde guardaremos parámetros y enumeraciones
  • menu.model.ts: que define la estructura de menú
Veamos el primero (config.model.ts):

/**
 * Configuration and base enums
 */

/**
 * Type of action in a menu
 */
export enum MenuAction {
    Menu = 0,    // Link to submenu
    Component,   // Link to a component
    Procedure,   // Link to a procedure
    URL          // link to an URL
}


Y ahora el segundo (menu.model.ts)

/**
 * Menu structure
 */
import { MenuAction } from './config.model'; // <-- import this

export class Menu {
  title: string;            // title of the menu
  actionType: MenuAction;   // Type of action as MenuAction
  action: string;           // action
  submenu: Menu;            // submenu
  info: string;             // Additional info

  constructor(title: string, actionType: MenuAction,
              info: string, action: string, submenu: Menu) {
  this.title = title;
  this.actionType = actionType;
  this.info = info;
  this.action = action ;
  this.submenu = submenu;
  }
}





jueves, 18 de mayo de 2017

Angular 2 y C3.css (1): Perspectiva inicial

1. Introducción


Vamos a crear una pequeña aplicación con Angular 2 y C3.css

La decisión de usar C3,css es:
  1. No tiene javascript, por tanto no deberíamos tener problemas con Angular2
  2. Es muy potente
  3. Es muy pequeña
  4. Y sobre todo porque es "responsive" y "mobile first"
Yo estoy utilizando Eclipse con Webclipse.

2. Creación del proyecto

Veamos los pasos que he hecho:

1. He creado un proyecto Angular 2
2. He descargado C3.css a la carpeta app/assets
3. En src/styles.css he puesto la ruta a C3.css


@import './assets/w3.css';

3. Diseño de la interfaz de usuario

Queremos tener un diseño parecido a este de W3Schools . No quiero redescubrir la rueda y utilizar recursos libres que parece que estan funcionando bien.



Para ello adaptamos a este diseño

+-------------------------------------------------+
| ☰              TITULO                          |
+------------+------------------------------------+
|            |                                    | 
| MENU       | ZONA DE CONTENIDO                  | 
| LATERAL    |                                    | 
| OCULTABLE  |                                    | 
|            |                                    | 
|            |                                    | 
+------------+------------------------------------+


Como vemos, queremos un panel lateral que se puede ocultar y mostrar que va a ser nuestro menú, y un panel de contenidos.

Ahora nos queda adaptar lo que nos da W3 al modo de actuar de Angular 2.

Para ello definiremos los siguientes elementos

1. Estructura de datos que guarde el menú (tipo árbol)
2. Componente del menú lateral (sidebar)
3. Componente del contenido principal
4. Servicio simple que proporcione la estructura de datos del menú lateral

De momento, para esta introducción ya tenemos demasiado. Mas adelante lo podemos complicar añadiendo mas components, barras de estado etc.

4. Estructura de datos del menú

Crearemos 2 ficheros 
  • config.model.ts: donde guardaremos parámetros y enumeraciones
  • menu.model.ts: que define la estructura de menú
Veamos el primero:

/**
 * Configuration and base enums
 */

/**
 * Type of action in a menu
 */
export enum MenuAction {
    Menu = 0,    // Link to submenu
    Component,   // Link to a component
    Procedure,   // Link to a procedure
    URL          // link to an URL
}


Y ahora el segundo

/**
 * Menu structure
 */
import { MenuAction } from './config.model'; // <-- import this

export class Menu {
  title: string;            // title of the menu
  actionType: MenuAction;   // Type of action as MenuAction
  action: string;           // action
  submenu: Menu;            // submenu
  info: string;             // Additional info

  constructor(title: string, actionType: MenuAction,
              info: string, action: string, submenu: Menu) {
  this.title = title;
  this.actionType = actionType;
  this.info = info;
  this.action = action ;
  this.submenu = submenu;
  }
}