2d Engine FLEX/FLASH for Android

This is my actionscript 2d engine made from scratch, It’s just to train in my tablet, but I can upload the code if somebody wants. Some features are:

- It can load xml maps generated with “Tiled”  tile map editor for every stage.

- Every stage can have a different look and feel, characters, sounds, items, perspective, characters behaviour, etc…  defined in the xml…

- It generates the graphics of a stage from a tileset png.

tilemini

- You can play any stage as a sidescroller game with gravity or in orthogonal perspective (from the top with x/y axis). It changes game mode and controls everytime a new stage is loaded so you can combine two kinds of games. (Isometric coming soon)

- Multi touch Joystick.

- The torch light stops when it finds a wall and then creates a shadow.

 2  3 4

FLEX 4.6, AIR 3, FlashPlayer 11

 

Adobe acaba de anunciar para octubre lo último en desarrollo movil por su parte.

http://www.adobe.com/devnet/flex/articles/whats-new-flex-flash-builder-46.html

 

Me encanta ver que han trabajado en el rendimiento, garantizando casi un nivel nativo:

…Adobe remains focused on performance, and in Flex 4.6 we’ve made considerable improvements. Many key performance optimizations have been made to give mobile applications an even more responsive feel. Simply repackaging an existing Flex mobile application with Flex 4.6 can yield up to a 50% performance gain. Creating a new application in Flex 4.6 will deliver near-native performance with the superior customization you expect from Flex.

Pero además, ya hay desarrollado un framework para programar juegos 2D y 3D que corran la api stage3d del nuevo FlashPLayer 11. O lo que es lo mismo aceleración por hardware por fin. Tutorial de ejemplo:

http://gotoandlearn.com/play.php?id=147

FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 5: Todo Junto

CONCEPTOS:

Este es el quinto y último ejemplo de la serie.

Este ejercicio va a ser una versión ultra simplificada, sin .jar demás en el pom y sin entrar en mayor complejidad que tener Maven Flex Spring y BlazeDS funcionando en conjunto sin errores.

NOTA:

Voy a seguir usando el plugin de Flex Builder 3 para eclipse Galileo. Se puede usar el SDK 4 de Flex y sustituir los tags mx por sus correspondientes spark.

Lo combinaré con Spring 3.0.6, Sppring-Flex integration 1.0.3 y BlazeDS 3.

 

Lo primero de todo es crear un proyecto de web dinámica java. Lo llamo “flexSpring3”. El build path lo apunto a WebContent/WEB-INF/classes.

Después incorparle las carpetas de blazeDS. (O crear uno importando el .war de blazeDS). Las carpetas a añadir en el WEB-INF del proyecto son “flex” y  “lib” de la version turkey de blazeDS como en anteriores ejemplos.

Con el proyecto web recién creado le añado el control de Maven: menú file/maven/enable dependency management.

Añado mi servidor apache al proyecto.

En el pom.xml añado las dependencias básicas para trabajar con mvc spring, anotaciones de spring, y la integración spring-flex:

<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>flexSpring3</groupId>
  <artifactId>flexSpring3</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>flexSpring3</name>
  <description>flexSpring3</description>

  <dependencies>
		<!-- spring 3 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>3.0.0.RELEASE</version>
        </dependency>
		<!-- spring 3 metadata support... -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>3.0.0.RELEASE</version>
        </dependency>
		<!-- integration with flex -->
        <dependency>
            <groupId>org.springframework.flex</groupId>
            <artifactId>spring-flex</artifactId>
            <version>1.0.3.RELEASE</version>
            <scope>test</scope>
        </dependency>
  </dependencies>
</project>

Con toda la estructura básica, empiezo a configurar y a conectar.

En primer lugar en web.xml, voy a configurar que todas las peticiones a la url /messagebroker/ las gestione un DispatcherServlet de Spring al que llamaré  Spring MVC Dispatcher Servlet:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>flexSpring3</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>

  <!--  PASO 0 -->
  	<!--a) Inicia Spring mvc con lo definido en el xml de configuración-->
	<servlet>
	    <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
	    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	    <init-param>
	        <param-name>contextConfigLocation</param-name>
	        <param-value>/WEB-INF/config/web-application-config.xml</param-value>
	    </init-param>
	    <load-on-startup>1</load-on-startup>
	</servlet> 

	<!--b) Indica que se Mapea las request a /messagebroker/+lo que sea-url, hacia Spring MVC Dispatcher Servlet-->
	<servlet-mapping>
   		 <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
   		 <url-pattern>/messagebroker/*</url-pattern>
	</servlet-mapping>
</web-app>

Voy a crear dicho Spring MVC Dispatcher Servlet, en una nueva carpeta “config” dentro del mismo WEB-INF.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:flex="http://www.springframework.org/schema/flex"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd

http://www.springframework.org/schema/flex

           http://www.springframework.org/schema/flex/spring-flex-1.0.xsd">

    <!--  PASO 1 -->
       <!-- definir el bean que va a usar Spring para comunicarse con FLEX. -->
     	<flex:message-broker/>
     	          <!--  El canal para la comunicación para las url con /messagebroker/
          	 va a ser el channel de tipo amf definido en services.config con el id="my-amf" -->

          	 <!--  que ese canal sea el por defecto, se indica en remoting-config.xml
          	 así como el adaptador para serializar/deserializar objetos java --> 	

	<!--  para poder usar anotaciones -->
	<context:annotation-config /> 

	<!--  Aqui spring busca entidades java para crear beans -->
	<context:component-scan base-package="com.flex" />
	<!--  en ese paquete está el bean con el servicio que saluda -->
</beans>

Puedo ver definido el bean que va a comunicar spring con flex a través de blazeDS. El tag para poder usar anotaciones spring en las entidades. Y el tag que indica que busque entidades para convertir en beans en la ruta com.flex .

Colgando del src de java creo el paquete com y dentro de él el paquete flex. Y dentro de él la clase Java:

package com.flex;

import org.springframework.flex.remoting.RemotingDestination;
import org.springframework.flex.remoting.RemotingInclude;
import org.springframework.stereotype.Service;

@Service("Hello")
@RemotingDestination
public class Hello {
	@RemotingInclude
	public String sayHello(String name){
		return "hello, " + name;
	}
}

Es la entidad que automáticamente Spring convertirá en el bean que a su vez será serializado a AMF y susministrado a Flex por medio de blazeDS.

Tiene la anotación @service para indicar que es un servicio con el nombre “Hello” y además la anotación @remotingDestination para indicar que puede este servicio puede ser solicitado a blazeDS desde Flex con un remote object con id de destination = id del servicio: “Hello”.

Este flujo de información serializada transcurre por un canal. El canal que usa blazeDS para la comunicación AMF por defecto es “my-amf”. Esto se puede ver en WEB-INF/flex/services-config.xml:

<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>

 

Ya puedo exportar el proyecto en .war y subirlo al servidor Tomcat y arrancarlo.

___________________________________________________________________

Ahora la parte en Flex. En la perspectiva Flex creo un new flex project. Abro el mxml principal y defino un objeto remoto y una etiqueta para mostrar el resultado.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	  layout="absolute"
	  creationComplete="robj.sayHello('Gonzalo')" >

	<mx:ChannelSet id="chnn">
		<mx:AMFChannel url="https://localhost:8080/flexSpring3/messagebroker/amf" />
	</mx:ChannelSet> 

	<mx:RemoteObject id="robj" destination="Hello"
		 channelSet="{chnn}"
		 endpoint="https://localhost:8080/flexSpring3/messagebroker/amf" />

	<mx:Label text="{robj.sayHello.lastResult}" />
</mx:Application>

Como voy a trabajar con una aplicación Flex desde local defino un canal y endpoint para el remote object apuntando al enpoint para el canal amf (antes expuesto en el cuadro superior marrón) del servidor  blazeDs de mi proyecto java, asu vez contenido en el servidor Apache Tomcat.

El atributo destination del remote object lo defino a “Hello” como en las anotaciones de la entidad java para indicar que era servicio y remotingdestination como expliqué más arriba.

También defino que en el evento onCreationComplete se llame al servicio pasando un string (“Gonzalo”) y que la etiqueta label mostrará la respuesta de la petición automáticamente por binding.

Al ejecutar la aplicación flex veo en la etiqueta “Hello Gonzalo”.

 

RESUMEN:

<!—When the Flex app. starts, it initiate a Flex Remoting request to the Tomcat server calling the Spring DispatcherServlet, which then will look up the service based on the destination Hello. This destination is automatically mapped to the Hello Bean. Then the sayHello method will be invoked on the bean, passing in the String that was specified in the RemoteObject call on the client. The method returns a new String, which is then serialized into AMF, inserted into the HTTP Response body, and sent back to the client. On the client side the Flex application will parse the AMF and then set the robj.sayHello.lastResult property to what was returned from the server. Data binding in the Label will note the property change and refresh its view of the data. –>

 

 

 

 

 

 

Posibles problemas:

evitarDolorCabeza();

Si cuando le doy a ejecutar en el ser servidor obtengo un error con el name space de flex, es porque no están desplegados los .jar del proyecto. Es decir están en el repositotio maven, pero no en la carpeta lib del .war que hay subido al apache. Solución:

*MAVEN exportar en el .war, las dependencias: Project properties/Java EE module dependencies, activar el tick en Maven dependencies.

 

 

Resto de la serie:

FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 0: Materiales
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 1: Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 2: JDBC
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 3: JDBC+Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 4: Hibernate+Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 5: Todo Junto

FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 4: Hibernate+Spring

 

CONCEPTO

Después de haber visto JDBC y JDBC spring para recoger valores de una tabla en BBDD llamada “users”, voy a usar Hibernate para hacer lo mismo. Con la gran diferencia de que no accedemos a la tabla, sino a un objeto que mapea la mapea y forma parte de la capa de persistencia.

Parto del proyecto finalizado del post anterior (JDBC+Spring). Básicamente lo que necesito para empezar es la clase User . (Y por supuesto conservar la tabla Users del ejemplo anterior, en la BBDD). 

Este post es parte de una serie de cinco. (Ver al final del post los enlaces a las entradas anteriores).

 

 

0) Preparar el framework. Para trabajar con Hibernate en Spring hace falta:

0.1) Incorporar las librerías necesarias. Maven las va a traer al proyecto si pongo en el nodo dependencies de pom.xml:

<!-- Para poder usar hibernate con spring -->
<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-orm</artifactId>
     <version>2.5.1</version>
</dependency>
<!-- Hibernate framework -->
<dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate</artifactId>
     <version>3.2.6.ga</version>
</dependency>
<!-- Para usar anotaciones con hibernate -->
<dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-annotations</artifactId>
     <version>3.3.1.GA</version>
</dependency>

La última dependencia es para poder configurar hibernate con anotaciones. Los mapeos de los objetos de la BBDD, se pueden hacer con XML (necesitaríamos crear un .hbm.xml por cada tabla…) o mediante anotaciones en las clases java. Voy a usar anotaciones.

evitarDolorCabeza();

Si encontramos más adelante el error: "Missing indirectly referenced artifact javax.transaction:jta:jar:1.0.1B:compile" es porque Maven no ha podido bajar tres librerías necesarias para transacciones con BBDD, por un problema de licenciamiento.

Se corrige descargando de: http://download.java.net/maven/2/javax/transaction/jta/1.0.1B/ los archivos: jta-1.0.1B.jar y jta-1.0.1B.jar.sha1 y jta-1.0.1B.jar.md5, y ubicándolos en la carpeta correspondiente del repositorio Maven: C:\Documents and Settings\user\.m2\javax\transaction\jta\1.0.1B

NOTA: Se puede aprovechar para ver en C:\Documents and Settings\user\.m2 (ruta por defecto), todas las utilidades que Maven va descargando y que son dependencias en los proyectos de esta serie de posts.

 

0.2) Crear en el xml de configuración de spring (applicationContest.xml), un Bean SessionFactory (Hilo seguro de conexión entre la BBDD y el mapeo)

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="configLocation" value="classpath:hibernate/hibernate.cfg.xml"/>
		<property name="hibernateProperties">
		<value>
		hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
		hibernate.query.substitutions=true 'Y', false 'N'
		hibernate.cache.use_second_level_cache=true
		hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
		hibernate.hbm2ddl.auto=update
		hibernate.use_sql_comments=true
		hibernate.show_sql=true
		</value>
		</property>
	</bean>

A destacar:

-Que su clase es org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean, disponible gracias a que hemos bajado el paquete spring-om con maven.

-Que se le inyecta el Bean dataSource en su propiedad del mismo nombre para que sepa con que BBDD trabaja.

-La ruta al XML de configuración de Hibernate ..classpath:hibernate/hibernate.cfg.xml

-Que se le especifica el dialecto de la BBDD en hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

 

0.3) Crear en el xml de configuración de hibernate. Para que coincida con lo especificado en el  xml de configuración de spring en el paso anterior, necesito una carpeta de recursos llamada “hibernate” que cuelgue de la carpeta de recursos que me creó maven. Hago menú-file-new-source folder, en el input “Folder name”, introduzco la ruta donde quiero que esté: src/main/resources/hibernate. Creo un nuevo XML llamado hibernate.cfg.xml y escribo en él:

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory name="sessionFactory">
		//TODO: Listar clases mapeadas
	</session-factory>
</hibernate-configuration>

 

 

1) Ya puedo mapear la tabla “users”:

1.1) Para ello en la clase “User” (com.glvalero.flexjava.usermanager.model.User), empleo las anotaciones dejándola:

package com.glvalero.flexjava.usermanager.model;
import java.util.List;
//HIBERNATE
//para generar autoincrementativos
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.GeneratedValue;

import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.JoinColumn;

@Entity
@Table(name="users")
public class User {

	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name="user_id")
	private int userId;

	@Column(name="forename")
	private String forename;

	@Column(name="surname")
	private String surname;

	//constructores
	public User() {}

	public User(int userId, String forename, String surname){

		this.userId = userId;
		this.forename = forename;
		this.surname = surname;
	}

	public User(String forename, String surname) {
		this.forename = forename;
		this.surname = surname;
	}
	//propiedades	
	public int getUserId() {
		return userId;
	}
	public void setUserId(int userId) {
		this.userId = userId;
	}

	public String getForename() {
		return forename;
	}
	public void setForename(String forename) {
		this.forename = forename;
	}

	public String getSurname() {
		return surname;
	}
	public void setSurname(String surname) {
		this.surname = surname;
	}
}

@Entity para crear la persistencia de esta entidad

@Table indica el nombre de la tabla en BBDD

@Id para indicar camplo clave

@GeneratedValue(strategy = IDENTITY) para indicar que sea autoincrementativo

@Column para indicar el nombre de la columna correspondiente en BBDD

 

 

Con las anotaciones se puede hacer mucho más, como crear tablas, añadir columnas desde java… Por ejemplo, puedo definir un mapeo a una tabla “Addresses” en Java aunque dicha tabla no exista en BBDD, ya que si no existe se Maven la creará. Para tener este tipo de sincronización entre los objetos persistentes y la BBDD hace falta un plugin. Maven lo instalará si grabo pom.xml poniendo bajo el nodo dependencies, el nodo build  con lo siguiente:


<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>JDBC</groupId>
  <artifactId>JDBC</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>mavenJDBC</name>
  <description></description>
    

  <dependencies>
	<!-- Conector BBDD -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.6</version>
		<type>jar</type>
		<scope>compile</scope>
  	</dependency>		

	<!-- Necesario para usar Spring plantillas JDBC -->
	<!-- Basico de Spring -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>2.5.6</version>
	</dependency>
	<!-- Plantilas JDBC de Spring -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-jdbc</artifactId>
		<version>2.5.6</version>
	</dependency>			

	<!-- Para poder usar hibernate con spring -->
	<dependency>
    	         <groupId>org.springframework</groupId>
    	         <artifactId>spring-orm</artifactId>
    	         <version>2.5.1</version>
	</dependency>
	<!-- Hibernate framework -->
	<dependency>
      	         <groupId>org.hibernate</groupId>
     	         <artifactId>hibernate</artifactId>
     	         <version>3.2.6.ga</version>
    	</dependency>
    	<!--  Para usar anotaciones con hibernate -->
    	<dependency>
      	         <groupId>org.hibernate</groupId>
      		<artifactId>hibernate-annotations</artifactId>
      	         <version>3.3.1.GA</version>
    	</dependency>
   </dependencies>  

   <build>
	<defaultGoal>install</defaultGoal>
	<plugins>
	    <plugin>
		<groupId>org.codehaus.mojo</groupId>
		<artifactId>hibernate3-maven-plugin</artifactId>
		<version>2.0-alpha-2</version>
		<configuration>
		    <components>
			<component>
			     <name>hbm2ddl</name>
		              <implementation>annotationconfiguration</implementation>
			</component>
		    </components>
		    <componentProperties>
			<drop>false</drop>
			<update>false</update>
			<jdk5>true</jdk5>
			<propertyfile>target/classes/jdbc.properties</propertyfile>
			<skip>${maven.test.skip}</skip>
		    </componentProperties>
		</configuration>
		     <executions>
			<execution>
			    <phase>process-test-resources</phase>
			    <goals>
			    <goal>hbm2ddl</goal>
			    </goals>
			</execution>
	              </executions>
	      </plugin>
         </plugins>
    </build>
 </project> 

 

Para comprobar que funciona voy a añadir desde java una columna a la tabla “Users”. La columna “address” que será una clave a otra tabla “addresses” que aun no he creado en MySQL. La relación es uno a uno (Un usuario puede tener solo una dirección y viceversa).

Añado en User, en el apartado de las variables mapeadas, las siguientes anotaciones:

@OneToOne(cascade = CascadeType.ALL)

@JoinColumn(name = "address_id")

private Address address;

 

Los import necesarios son import javax.persistence.JoinColumn;

import javax.persistence.OneToOne; y import javax.persistence.CascadeType;

(Con cascadeType.All sincronizo los cambios de tal manera que cuando se actualiza el objeto persistente se actualiza la BBDD)

También añado los getter/setter para la nueva variable address dejando la clase así:

 

package com.glvalero.flexjava.usermanager.model;
import java.util.List;
//HIBERNATE
//para generar autoincrementativos
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.GeneratedValue;

import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Column;
import javax.persistence.Id;
//para la cración de la columna address y su reación con la tabla t_address
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.CascadeType;

@Entity
@Table(name="users")
public class User {

	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name="user_id")
	private int userId;

	@Column(name="forename")
	private String forename;

	@Column(name="surname")
	private String surname;

	@OneToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = "address_id")
	private Address address;

	//constructores
	public User() {}

	public User(int userId, String forename, String surname){

		this.userId = userId;
		this.forename = forename;
		this.surname = surname;
	}

	public User(String forename, String surname) {
		this.forename = forename;
		this.surname = surname;
	}
	//propiedades	
	public int getUserId() {
		return userId;
	}
	public void setUserId(int userId) {
		this.userId = userId;
	}

	public String getForename() {
		return forename;
	}
	public void setForename(String forename) {
		this.forename = forename;
	}

	public String getSurname() {
		return surname;
	}
	public void setSurname(String surname) {
		this.surname = surname;
	}

	public Address getAddress() {
		return address;
	}
	public void setAddress(Address address) {
		this.address = address;
	}
}

 

Falta crear la clase Address, en el mismo paquete que la clase User:

package com.glvalero.flexjava.usermanager.model;

import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="addresses")
public class Address {

	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "address_id")
	private Integer addressId;
	@Column(name = "street")
	private String street;
	@Column(name = "postcode")
	private String postCode;
	@Column(name = "city")
	private String city;
	@Column(name = "country")
	private String country;
	public Integer getAddressId() {
	return addressId;
	}
	public void setAddressId(Integer addressId) {
	this.addressId = addressId;
	}
	public String getStreet() {
	return street;
	}
	public void setStreet(String street) {
	this.street = street;
	}
	public String getPostCode() {
	return postCode;
	}
	public void setPostCode(String postCode) {
	this.postCode = postCode;
	}
	public String getCity() {
	return city;
	}
	public void setCity(String city) {
	this.city = city;
	}
	public String getCountry() {
	return country;
	}
	public void setCountry(String country) {
	this.country = country;
	}

}

 

Ya están mapeadas.

 

1.2) Falta indicar a hibernate que objetos de la BBDD van a persistir en hibernate.cfg.xml. Incluyo los nodos mapping con las clases User y Address recien creadas:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory name="sessionFactory">
		<mapping class="com.glvalero.flexjava.usermanager.model.User" />
		<mapping class="com.glvalero.flexjava.usermanager.model.Address" />
	</session-factory>
</hibernate-configuration>

 

En este punto si ejecuto la aplicación, la consola muestra la tabla empleados, como en el post anterior “JDBC+Spring”, ya que no he cambiado nada en el Main.java y se sigue consultando la BBDD con JDBC. Además, aparecen trazas relativas a la creación de la tabla “addresses”, etc… y es que Maven ha creado la tabla con su clave ajena, etc… por mí,  y puedo comprobarlo abriendo MySQL Query Browser.

 

 

______________________________

 

Ahora voy a sustituir esa funcionalidad JDBC de consulta a BBDD, por la consulta al objeto en la capa de persistencia. Va bastar con crear una nueva clase de acceso a datos, definir en el xml de configuración de spring el Bean que la empleay en el main instanciarlo a él en vez de al Bean para JDBC. Esos pasos son:

1) Clase de acceso de datos. Lo primero que hago es crear un paquete: com.glvalero.flexjava.usermanager.model.hibernate, y dentro una clase llamada UserDAO_hibernate que al igual que la clase usada en JDBC spring, implementa dos interfaces. La interface UserDAO para garantizarnos que dispondremos del método findAll() y también implementa la interface HibernateDaoSupport para la plantilla hibérnate para contactar con los objetos persistentes. (OJO ya no contacto con BBDD como con JDBC, sino con los objetos que la mapean). La clase queda:

package com.glvalero.flexjava.usermanager.model.hibernate;

import java.util.List;

import com.glvalero.flexjava.usermanager.model.User;
import com.glvalero.flexjava.usermanager.model.UserDAO;

import org.hibernate.Query;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class UserDAO_hibernate extends HibernateDaoSupport implements UserDAO {

	@SuppressWarnings("unchecked")
	public List<User> findAll() {
		String HQL = "from User";
		Query query = getSession().createQuery(HQL);
		return (List<User>)query.list();
	}
}

* La consulta es a un objeto no a una tabla por eso usa el lenguaje HQL (no cubierto en este post). Se podría hacer con SQL estandar ( getSession().createSQLQuery(sql) ) .

2) En el appcontext.xml crear el bean que usará esa clase DAO. En la propiedad sessionFactory pasamos el id del bean sessionFactory que es la capa de persistencia. (En jdbc spring pasaba el datasource, la BBDD)

<bean name="userDaoH" class="com.glvalero.flexjava.usermanager.model.hibernate.UserDAO_hibernate">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>	

Quedando el xml de configuración de spring así:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- Bean de conexión a BBDD -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${jdbc.driverClassName}"/>
		<property name="url" value="${jdbc.url}"/>
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
	</bean>
	<!--  Esas variables las coge de el fichero externo jdbc.properties:  -->
	<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
		<list>
			<value>classpath:jdbc.properties</value>
		</list>
		</property>
	</bean>

	<!-- Bean Data object access que consulta la tabla usuarios, le inyectamos la conexión a BBDD en la propiedad datasource, esa propiedad
	viene  en la plantilla spring jdbc de la que extiende la clase jdbc.UserDAO_jdbc_spring  -->
	<bean name="userDao" class="com.glvalero.flexjava.usermanager.model.jdbc.UserDAO_jdbc_spring">
		<property name="dataSource" ref="dataSource" />
	</bean>

	<!--  Bean que consulta la capa de persistencia hibernate, le inyectamos dicha capa en la propiedad sessionFactory, esa propiedad
	viene  en la plantilla spring hibernate de la que extiende la clase jdbc.UserDAO_hibernate -->
	<bean name="userDaoH" class="com.glvalero.flexjava.usermanager.model.hibernate.UserDAO_hibernate">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>	

	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="configLocation" value="classpath:hibernate/hibernate.cfg.xml"/>
		<property name="hibernateProperties">
		<value>
		hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
		hibernate.query.substitutions=true 'Y', false 'N'
		hibernate.cache.use_second_level_cache=true
		hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
		hibernate.hbm2ddl.auto=update
		hibernate.use_sql_comments=true
		hibernate.show_sql=true
		</value>
		</property>
	</bean>

</beans>

 

3) Solo queda usarla en el Main, para ello comento la línea que solicitaba el bean jdbc y añado la petición al bean que trabaja con la capa de persistencia hibérnate:

import com.glvalero.flexjava.usermanager.model.*;
import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {

		//paso 1 leer el XML de los beans
		ApplicationContext context = new ClassPathXmlApplicationContext("appContext.xml");
		//2, crear un Data object access a partir del bean con id userDao
		//jdbc_spring bean				
		//UserDAO userDao = (UserDAO)context.getBean("userDao");		
		//hibernate bean
		UserDAO userDao = (UserDAO)context.getBean("userDaoH");

		//3, llamar al métodoque recoge los resultados de la tabla en un List
		List<User> users = userDao.findAll();
		for (User user : users)
			System.out.println("--->" + user.getForename() + " " + user.getSurname() );	

	}

}

 

Ejecutar y ver el listado recuperado de la capa de persistencia además de la query de hibernate.

 

 

Esquema final del proyecto. Observo todas las librerías que maven ha bajado por mí para poder trabajar con mysql, JDBC, spring, hibernate…

image

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 0: Materiales
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 1: Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 2: JDBC
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 3: JDBC+Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 4: Hibernate+Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 5: Todo Junto

FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 3: JDBC+Spring

Aquí también el objetivo es conectarse con Java a una BBDD y con una select recoger los valores en un List[], pero en vez de con JDBC clásico como en el tutorial 2, con JDBC incorporándole la plantilla simple de spring para JDBC.

Una de las ventajas que supone éste método es ahorrar código repetido en las conexiones, en las operaciones select, update, delete… hay métodos preconstruidos para esas operaciones clásicas y que recogen los resulsets, los errores se manejan mejor, etc…

Spring manejará internamente la conexión, su cierre, las excepciones, etc que definimos en el tutorial anterior de la manera clásica dentro de los try/catch.

Este ejemplo parte del proyecto del tutorial 2 (JDBC), pero yo he creado uno nuevo a raíz de ese para dejar el anterior intacto.

La idea es que crear una nueva clase que conecte con la BBDD usando las plantillas de spring en vez de la forma clásica. Esa clase implementará la interface userDAO.java para garantizar que la aplicación no falla al sustituir en el Main la anterior forma de acceso por la nueva ya que ambas clases contendrán por fuerza el método findAll() que es el que busca a los usuarios en la BBDD. También extiende de SimpleJdbcDaoSupport para poder usar la plantilla básica de Spring jDBC y poderle inyectar la conexión a BBDD. Esta clase será UserDAO_jdbc_spring:

 

1) La clase a crear es UserDAO_jdbc_spring en el paquete com.glvalero.flexjava:

package com.glvalero.flexjava.usermanager.model.jdbc;

import java.util.List;
import com.glvalero.flexjava.usermanager.model.*;

//plantillas spring:
import org.springframework.jdbc.core.simple.ParameterizedBeanPropertyRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;

public class UserDAO_jdbc_spring extends SimpleJdbcDaoSupport implements UserDAO {

	public List<User> findAll() {
		//esto reemplaza todo el código de UserDAO_jdbc_classic, la conexión, cerrarla, errores, mapeo del objeto resultado de la query...
		String sql="SELECT * FROM users";
		return getSimpleJdbcTemplate().query(sql,ParameterizedBeanPropertyRowMapper.newInstance(User.class));
	}

}

La reducción de código salta a la vista, simplemente tengo una linea donde defino la query, y en que objeto se guardará el resultado.

 

Pero da errores, no encuentra las librerías Spring y además no hemos definido las Beans que internamente spring usa para el mapeo de la consulta.

2) Para solucionarlos, en primer lugar, le decimos a Maven que nos traiga lo que necesitamos para trabajar con Spring jdbc incluyendo las dependencias necesarias en pom.xml:

<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>JDBC</groupId>
  <artifactId>JDBC</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>mavenJDBC</name>
  <description></description>
	<!-- Conector BBDD -->
	<dependencies>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.6</version>
			<type>jar</type>
			<scope>compile</scope>
  		</dependency>	

		<!-- Necesario para usar Spring plantillas JDBC -->
		<!-- Basico de Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>2.5.6</version>
		</dependency>
		<!-- Plantilas JDBC de Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>2.5.6</version>
		</dependency>
	</dependencies>
 </project>

 

Veo que desaparecen errores y que en la parte del explorador de la solución se ha incluido el .jar necesario en Maven dependencies.

 

En segundo lugar, en el paquete src/main/resources hago menú file/new/Spring Bean Configuration file, y lo llamo applicationContext.

Aquí hay que crar el bean que conecta con la BBDD:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
	<property name="driverClassName" value="${jdbc.driverClassName}"/>
	<property name="url" value="${jdbc.url}"/>
	<property name="username" value="${jdbc.username}"/>
	<property name="password" value="${jdbc.password}"/>
</bean>

Los parámetros son variables que va a leer en un archivo con extensión .properties llamado jdbc, que voy a crear en la carpeta src/main/resources. En el escribo:

   jdbc.driverClassName=com.mysql.jdbc.Driver

   jdbc.url=jdbc:mysql://localhost:3306/javajdbc

   jdbc.username=root

   jdbc.password=admin

applicationContext..xml completo queda así:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- Bean de conexión a BBDD -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${jdbc.driverClassName}"/>
		<property name="url" value="${jdbc.url}"/>
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
	</bean>
	<!--  Esas variables las coge de el fichero externo jdbc.properties:  -->
	<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
		<list>
			<value>classpath:jdbc.properties</value>
		</list>
		</property>
	</bean>

	<!-- Bean Data object access que consulta la tabla usuarios (jdbc.UserDAO_jdbc_spring), le inyectamos la conexión a BBDD en la propiedad datasource, 

         esa propiedad está en la plantilla spring jdbc, y puedo acceder a dicha propiedad porque la clase extiende a la plantilla donde está declarada la propiedad-->
	<bean name="userDao" class="com.glvalero.flexjava.usermanager.model.jdbc.UserDAO_jdbc_spring">
		<property name="dataSource" ref="dataSource" />
	</bean>
</beans>

 

3) Ahora hay ejecutarlo todo desde el main:

import com.glvalero.flexjava.usermanager.model.*;
import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {

		//paso 1 leer el XML de los beans
		ApplicationContext context = new ClassPathXmlApplicationContext
		("applicationContext.xml");
		//crear un Data object access a partir del bean con id userDao
		//al que le corresponde la clase UserDAO_jdbc_spring
		UserDAO userDao = (UserDAO)context.getBean("userDao");

		//llamar al método que tiene para recoger los resultados de la tabla en un List
		List<User> users = userDao.findAll();
		for (User user : users)
			System.out.println(user.getForename() + " " + user.getSurname() );	

	}
}

 

Tras ejecutar vemos el listado de los tres usuarios en la consola de eclipse.

 

El proyecto queda así:

image

 

 

 

 

 

 

 

 

 

 

 

 

 

 

FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 0: Materiales
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 1: Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 2: JDBC
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 3: JDBC+Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 4: Hibernate+Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 5: Todo Junto

FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 2: JDBC

CONCEPTO

Java Data Base Conector. En este post conecto de la manera tradicional Java con una BBDD MySQL que antes instalaré.

El objetivo es poder comparar en el siguiente tutorial (JDBC+Spring) lo mismo hecho con las plantillas de Spring para JDBC y ver la reducción de código empleado y las demás ventajas que aporta.

NOTAS

El objetivo de la aplicación será hacer una select y recoger los valores de la tabla usuarios en un List[] y mostrarlos por consola.

Maven me va a descargar el driver necesario para conectar con MySQL. La ruta a ese driver se pasa en la cadena de conexión. En el siguiente tutorial pondré los datos de conexión en un fichero .properties externos).

El entorno de desarrollo para poder hacer el ejemplo, se creo en la parte 0 de esta serie de posts. 

 

1) CREAR LA BBDD:

Abrir MySQL Query Browser

En la primera pantalla, en la opción “stored conection” pulso sobre los puntos suspensivos y en la ventana que se despliega, creo una nueva conexión, rellenando simplemente el nombre para la conexión y el host que será mi equipo (localhost):

image Aplicamos y cerramos.

 

En la ventana inicial, selecciono la conexión recién creada, e introduzco usuario: “root”, password: “admin” (la que puse al instalar MySQL), y además un nombre de esquema de BBDD (javaDatabase), como no existe me preguntará que si deseo crearlo, digo que si y se me abre la aplicación:

Ya está disponible el nuevo esquema:

image

 

Voy a crear la tabla users. En el area de SQL query escribo:

CREATE TABLE `javadatabase`.`users` (

`user_id` bigint(20) NOT NULL auto_increment,

`forename` varchar(50) NOT NULL,

`surname` varchar(50) NOT NULL,

PRIMARY KEY (`user_id`)

) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1

 

Pulso ejecutar (botón rayo)

Ahora puedo hacer botón derecho/refresh sobre el esquema javadatabase y ver que de él cuelga la nueva tabla users. En ella inserto tres usuarios:

INSERT INTO `users` (`forename`, `surname`) VALUES (‘Michael’,'Davis’);

INSERT INTO `users` (`forename`, `surname`) VALUES (‘Paul’,'Roberts’);

INSERT INTO `users` (`forename`, `surname`) VALUES (‘Tom’,'Newman’);

 

2) Creo en eclipse un nuevo proyecto Maven simple: (new/others/maven/maven Project y marco la opción “Create simple proyect”)

image

 

Hay que crear la clase Java que mapee la tabla de usuarios de la BBDD que acabamos de crear.

Creo en src/main/java la siguiente estructura de paquetes por ejemplo com.glvalero.flexjava.usermanager.model. Y dentro, la clase “User” acorde con la tabla users:

package com.glvalero.flexjava.usermanager.model;

public class User {
	private int userId;
	private String forename;
	private String surname;
	//constructores
	public User() {}

	public User(int userId, String forename, String surname){
		this.userId = userId;
		this.forename = forename;
		this.surname = surname;
	}
	//constructor sin id, para usarlo en insert en una tabla con el id autoincrementativo
	public User(String forename, String surname) {
		this.forename = forename;
		this.surname = surname;
	}
	//propiedades	
	public int getUserId() {
		return userId;
	}
	public void setUserId(int userId) {
		this.userId = userId;
	}

	public String getForename() {
		return forename;
	}
	public void setForename(String forename) {
		this.forename = forename;
	}

	public String getSurname() {
		return surname;
	}
	public void setSurname(String surname) {
		this.surname = surname;
	}
}

En el mismo paquete voy a crear la interface para las clases que manejarán esos objetos:

package com.glvalero.flexjava.usermanager.model;
import java.util.List;

//Es la interface para todas las clases que usen usuarios
public interface UserDAO {
	//implementarán como mínimo un metodo "findAll" que devuelve una lista de usuarios
	//(del tipo User que está en este paquete)
	List<User> findAll();
}

*La voy a usar para garantizarme que en el siguiente post, la clase que cree usando la plantilla de spring, tenga también el método findAll y sea cómodo usar una u otra (conexión clásica JDBC / conexión JDBC con plantilla spring).

 

Ahora la clase que implementará esa interface y hace una select en la tabla usuarios. Dentro del paquete actual, creo un nuevo paquete “jdbc”, y en él la clase UserDAO_jdbc_classic. (DAO acrónimo de Data Access Object)

package com.glvalero.flexjava.usermanager.model.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.glvalero.flexjava.usermanager.model.*;

public class UserDAO_jdbc_classic implements UserDAO{

	private String driverClassName;
	private String url;
	private String username;
	private String password;

	public UserDAO_jdbc_classic(String driverClassName, String url,
		String username, String password) {
		this.driverClassName = driverClassName;
		this.url = url;
		this.username = username;
		this.password = password;
	}

	public List<User> findAll() {
		List<User> usersList = new ArrayList<User>();
		String sql = "SELECT * FROM users";
		Connection conn = null;

		try {
			Class.forName(driverClassName); //-1-
			conn = DriverManager.getConnection(url, username, password);
			PreparedStatement ps = conn.prepareStatement(sql);
			ResultSet rs = ps.executeQuery();

			while (rs.next()) {
				int userId = rs.getInt("user_id");
				String forename = rs.getString("forename");
				String surname = rs.getString("surname");
				usersList.add(new User(userId, forename, surname));
			}
			rs.close();
			ps.close();

		} catch (SQLException e) {
			throw new RuntimeException(e);
		} catch (ClassNotFoundException e) {
			//-1-: salta si no encuentra la clase  (Class.forName(driverClassName);)
			//eso quiere decir que no tenemos instalado ese driver y tendremos que descargar los drivers de JDBC		
			e.printStackTrace();
		} finally {
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
				}
			}
		}

		return usersList;
	}

}

 

3) Ahora le decimos a Maven que nos baje los drivers para conectar con java con mysql creando la dependencia adecuada, de tal manera que el pom.xml queda:

<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>JDBC</groupId>
  <artifactId>JDBC</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>mavenJDBC</name>
  <description></description>
	<dependencies>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.6</version>
			<type>jar</type>
			<scope>compile</scope>
  		</dependency>
	</dependencies>
  </project>

 

 

4) Finalmente la clase Main que instancie a UserDAO_jdbc_classic para que nos devuelva los usuarios:

import com.glvalero.flexjava.usermanager.model.*;
import com.glvalero.flexjava.usermanager.model.jdbc.UserDAO_jdbc_classic;

import java.util.List;

public class Main {

	private static final String JDBC_DRIVE_CLASS_NAME = "com.mysql.jdbc.Driver";
	private static final String JDBC_URL = "jdbc:mysql://localhost:3306/javajdbc";
	private static final String JDBC_USERNAME = "root";
	private static final String JDBC_PASSWORD = "admin";

	public static void main(String[] args) {
		UserDAO userDao = new
		UserDAO_jdbc_classic(JDBC_DRIVE_CLASS_NAME, JDBC_URL, JDBC_USERNAME, JDBC_PASSWORD);
		List<User> users = userDao.findAll();

		for (User user : users)
			System.out.println(user.getForename() + " " + user.getSurname() );
	}

}

 

Ejecuto la aplicación y veo en la consola a los tres usuarios recuperados de la BBDD.

 

FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 0: Materiales
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 1: Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 2: JDBC
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 3: JDBC+Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 4: Hibernate+Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 5: Todo Junto

FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 1: Spring

CONCEPTOS

Spring es un framework modular basado en POJOs.

Un POJO (plain old java object) es un objeto sencillo, instanciado a partir de una clase básica (varias variables y sus getter setter por ejemplo).

El framework además se apoya por un lado en el concepto Inversion of Control (El control va al contrario que en las aplicaciones por procedimientos que tienen una pieza central que controla la lógica y llama a las subrutinas específicamente diseñadas para una tarea concreta como atacar una BBDD por ejemplo, aquí cada subrutina es un objeto lo más genérico posible que encapsulará dinámicamente su funcionamiento siendo reutilizable). Y por otro lado, en el patrón de diseño Dependency Injection.

Un objeto manejado por el contenedor Spring es un “bean”.

NOTAS

La inyección de dependencias entre los objetos se puede hacer por el constructor de los objetos o a través de sus setter. El tipo de inyección de dependencias a usar en el tutorial será por setter.

El plugin Maven nos ayuda a crear la estructura del proyecto e importa las librerías que necesitamos para el framework spring, entre otras muchas cosas que puede hacer.

El entorno de desarrollo para poder hacer el ejemplo, se creo en la parte 0 de esta serie de posts.

 

1) Comienzo creando un nuevo proyecto maven: menú new/others/maven/maven project

-Marco create simple project, de momento no usamos arqueotipos. (Maven nos puede crear la estructura completa de un proyecto que use el MVC Cairngorm de FLEX por ejemplo)

-Y elijo mi workspace definiendo la ruta del proyecto.

-En la siguiente pantalla,

-Groupid = ruta del proyecto en el repositorio maven. (Para cuando usemos comandos para instalarlo por consola, etc) Yo le asigno por ejemplo  = com.glvalero.flexJava.spring1

-ArtifactId = nombre del proyecto en el eclipse = “spring1”

-Packaging = elegimos jar porque este proyecto no es web y no necesitamos un jar

-name = nombre descriptivo del proyecto Maven = Maven spring1

clip_image002

Tras aceptar nos crea la estructura básica del proyecto y el xml clave desde el que maven gestiona las dependencias del proyecto, pom.xml.

 

2) Crear dependencias es muy sencillo. Por ejemplo, para que maven nos importe el solito el jar de spring que necesitaremos, ponemos en el pom.xml:

<dependencies>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>2.5.6</version>
	</dependency>
</dependencies>

 

Pongo el eclipse en perspectiva java EE y veo en el solution explorer las librerías de spring que me ha traido.

En perspectiva flash, las dependencias las vemos haciendo click derecho sobre el proyecto/java build path. Ahí vemos que está spring-context y otras necesarias para funcionar con lo mínimo para spring. (Si tenemos un warning del JRE, hacemos doble click sobre la librería JRE y cambiamos al jre del jdk que tengamos (c:/java/jdk 1.6.x/fre))

clip_image004

Hacemos saber a eclipse que estamos en un proyecto spring: Click derecho sobre el proyecto, spring tools, “Add Spring Project Nature,”

 

3) Una vez configurado el proyecto Maven y descargado e instalado el framework de spring puedo picar Java:

-Creo un paquete en src.main.java que sea com.glvalero.hello

-Creo dos clases Hello y Message:

package com.glvalero.hello;

public class Message {
	private String text;

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}
} 
package com.glvalero.hello;

public class Hello {

	private Message message;

	public void sayHello() {
		System.out.println("Hello Gonzalo!" + message.getText());
	}

	public void setMessage(Message message) {
		this.message = message;
	}

	public Message getMessage() {
		return this.message;
	}
}

Message, es simplemente para instanciar un objeto con un string privado y sus getter y setter.

Hello, para instanciar un objeto con una variable de tipo  Message anteriormente mencionado, sus getter/setter, y un método para sacar el texto del mensaje por consola.

 

¿Quien declara instancias de estos objetos?, ¿Quién va a hacer que Hello instancie un Message?:

4) La respuesta es el controlador de beans spring que voy a crear. Para crear este archivo de configuración, en el explorador de la solución, hago con el ratón click derecho sobre la carpeta /src/main/resources/ y elijo New-Other-“Spring Bean Configuration file” y lo llamaré ApplicationBeans.xml y clico en finalizar. Abro ApplicationBeans.xml recién creado y le añado dos beans uno para cada clase de java quedando así:

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans ??
http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="message" class="com.glvalero.hello.Message" >
		<property name="text" value="How are you?" />
	</bean>

	<bean id="hello" class="com.glvalero.hello.Hello">
		<property name="message" ref="message" />
	</bean>

</beans>

 

Explico el XML. Cada nodo bean, tiene un atributo “id” con un valor único y un atributo class que dice de que clase instancia.

El bean con id="message”: Internamente spring crea un bean apartir de la clase com.glvalero.hello.Message asignándole el id “message” y asigna valor a”How are you” a la variable “text” usando el setter setText cuando dice <property name="text" value="How are you?" />

Bean id=" hello”: <property name="message" llamará al setter setMessage y el valor que le pasará será el bean con id=“message (es decir el de arriba con el saludo) indicándolo en  el atributo ref="message".

 

5) Solo falta crear un main.java que instancie el contenedor spring e inicie la aplicación.

package com.glvalero.hello;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationBeans.xml");

		Hello helloWorld = (Hello) context.getBean("hello");
		helloWorld.sayHello();
	}
}

Al ejecutar como aplicación vemos en la consola: How are you?

La aplicación a instanciado el xml de contexto de spring. Y después en un objeto Hello hemos metido el bean que nos devuelve spring con el id “hello”. Al instanciarlo spring ve en el xml que tiene que instanciar otro con el mensaje e inyectárselo. Podríamos tener otro saludo distinto y asignarlo en el xml de contexto cambiando el id del atributo ref al del nuevo bean, la aplicación sin tener que compilar nos devolvería otro saludo.

 

FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 0: Materiales
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 1: Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 2: JDBC
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 3: JDBC+Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 4: Hibernate+Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 5: Todo Junto

FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 0: Materiales

Esta es la introducción de una serie de ejemplos que voy a postear sobre tecnología empresarial Java con cliente en FLEX.

Como punto de partida recomiendo el libro Beginning Java and Flex Migrating Java, Spring, Hibernate, and Maven
Developers to Adobe Flex. A pesar del título, es de las pocas publicaciones que no está orientada a profesionales veteranos en Java centrándose únicamente en explicar un poco de FLEX y la comunicación con Java. No, este libro, viene muy bien para usuarios avanzados de FLEX que deseen adquirir buenos fundamentos en Java empresarial y los´frameworks más extendidos, como plus o para ser desarrollador ambivalente J2ee/FLEX.

 

Mi entorno de desarrollo emplea lo siguiente:

0) JDK 1.6.x

1) Eclipse 3.5 Galileo. Instalarle desde menú/help/instalar software los siguientes plugins:

-Plug-in SpringIDE. URL para el instalador de plugins de eclipse = http://springide.org/updatesite

(options Core, Extension(Incubation), and Extension of SpringIDE tools).

clip_image002

(En la imagen marco los tres, pero es mejor hacerlo de una en una, por orden e ir reiniciando, si no fallan porque tienen dependencia entre si)

-Plug-in JBoss Hibernate (herramientas que mejoran la productividad con hibérnate) URL para el instalador de plugins de eclipse = http://download.jboss.org/jbosstools/updates/stable/galileo . En el filtro poner “hibérnate” y seleccionar todos.

 

2) MySql 5.1 (Siguiente, siguiente…) admin/admin

- MySQL GUI Tools Bundle

3) Apache 6

4) MAVEN

Con Maven se puede crear, testear y subir proyectos al servidor. Pero sobre todo sirve para tener un repositiorio de librerías comunes. Veremos más adelante lo sencillo que es en el xml de configuración, crear una dependencia, por ejemplo a las librerías de spring, o de conexión con MySQL. Eso hace que se descarguen a nuestro equipo y el proyecto compile bien, además al estar almacenándose en la ruta maven dada al crear el proyecto maven, después es reutilizable para otros proyectos que las usen también, o para decir que este proyecto ahora usa este driver o esta versión de tal framework simplemente con modificar su xml de dependencias. Facilita el desarrollo y el mantenimiento.

- Maven: descargar desde el navegador yendo a http://Maven.apache.org/download.htm (He descargado la versión 2.0.11 a pesar de existir la 3 ya que la manera de trabajar con el xml principal es distinta y la mostraré más adelante)

Descomprimir en C: como el apache y poner en las variables de entorno, en PATH: c:\apache-maven-x.x.x\bin  (cambiar las x por la versión descargada). Para probar que funciona abrir un cmd y poner mvn –version

- Y después Plug-in Maven para eclipse. Desde el instalador de sofware de eclipse: http://m2eclipse.sonatype.org/sites/m2e

5) FLEX plug-in (podría usar directamente el Flash Builder 4.5 (último actualmente) y haberle instalado lo anterior, pero me faltarían plugins de J2ee que vienen por defecto en eclipse galileo J2ee, así que yo he instalado el plugin FB 4 sobre mi versión existente y actualizada de eclipse galileo que es más que suficiente para cumplir con los objetivos de esta serie de posts. Es interesante usar unas veces Flash Builder standalone y otras el Plugin para eclipse, por eso en mis post van alternando. Ambas herramientas pueden usarse en nuestro futuro empleo.

 

 

FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 0: Materiales
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 1: Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 2: JDBC
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 3: JDBC+Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 4: Hibernate+Spring
FLEX/BlazeDS/Java+Maven+Spring+Hibernate+MySQL. Parte 5: Todo Junto

Optimizando con Flash Builder 4.5 un ANDROID GAME

Hace mucho que no posteo. Estoy llevando a cabo un proyecto nuevo en mis ratos libres. Un motor para un videojuego que sea capaz de alternar fases en perspectiva isométrica, vista lateral y ortogonal. 

Lo más importante es el trabajo de optimización.

Adobe nos facilita un montón de cosas para el desarrollo Android. En mi caso, desarrollo para una tablet Samsung Galaxy Tab y basta con conectarla al pc y hacer debug para ver los resultados e ir depurando. Pero podría elegir entre uno de los muchos simuladores que incluye como el del htc desire por ejemplo.

Gracias al profiler podemos minimizar el uso de memoria RAM de la aplicación. En mi juego, aun en sus primeros pasos, al cambiar de mapa podía ver como se duplicaban las instancias. Un mapa consta de 196 tiles (14 casillas de alto por 14 de ancho), sin contar con el heroe, y los objetos que encuentra. Si cada vez que cambiamos de mapa añadimos 200 objetos a la memoria, en un dispositivo móvil puede ser crítico. Se puede ver en la imagen que el número de instancias de mis tiles (cuadros que componen el mosaico) permanece en 196, también podemos ver que de esas 196 tiles, 139 son de tipo “tile_0” (espacioes en negro) y 56 son “tile_1” (obstáculos verdes) y un montón de información:

 

1

 

Al cambiar de mapa, las instancias siguen en 196, con distinta proporción de huecos/obstáculos. Se puede ver que aun hay algo incorrecto porque se ha generado una nueva instancia del controlador del joystick que hay que solocionar:

2

Más adelante mostraré las buenas prácticas para la gestión de la memoria (tan escasa en estos dispositivos móviles). Usar vectores en vez de array, eliminar instancias, reusar objetos, no instanciar en bucles…

El proyecto usa un framework propio MVC, una versión muy simplificada de cairngorm. Dos patrones singleton, uno para los datos y otro para el controlador del orden de cargas, pantallas…, un sistema de carga de mapas que permite indicar la librería gráfica que usa cada mapa (mapa de la cueva, mapa del hospital… cada uno con su diseño de tiles), un joystick que se adapta a perspectiva ortogonal (la que se ve en los pantallazos) e isométrica. Algunas otras cosas útiles para minimizar el esfuerzo de la aplicación móvil, como por ejemplo un pool de objetos:

package com.code.util
{
	import flash.display.MovieClip; 

	public final class ItemPool
	{
			private static var MAX_VALUE:uint;
			private static var counter:uint;
			private static var pool:Vector.<MovieClip>;
			private static var currentSprite:MovieClip; 

			public static function initialize( maxPoolSize:uint):void
			{
				MAX_VALUE = maxPoolSize;
				counter = maxPoolSize; 

				var i:uint = maxPoolSize; 

				pool = new Vector.<MovieClip>(MAX_VALUE);
				while( --i > -1 )
					pool[i] = new MovieClip();
			} 

			public static function getSprite():MovieClip
			{
				if ( counter > 0 )
					return currentSprite = pool[--counter]; 

			} 

			public static function disposeSprite(disposedSprite:MovieClip):void
			{
				pool[counter++] = disposedSprite;
			} 

	}
}

Esta táctica nos permite no intanciar Movieclips de más, ya que nos devuelve el siguiente disponible en un vector. Después de usarlo podemos liberarlo y dejarlo disponible. También podríamos dejarlos a null y forzar un garbage collector para hacerlos desaparecer ya que tenemos controladas que instancias hay dentro del vector. Al tener el tipo fijado, un vector es mucho más rápido que un array. Si no usamos linea de tiempo Sprite es más recomendable que MovieClip desde luego.

Aunque los resultados del multitouch no son los que me gustarían en cuanto a constancia en el framerate. hay que reconocer el trabajo de Adobe en esta entrega de Flash Builder sobre todo en cuanto a lo fácil que ha hecho testear y hacer debug. Espero con ganas la versión 2.7 de AIR para dispositivos móviles y que la ganancia en rendimiento sea cada vez mayor.

Servidor BlazeDS

Los ejemplos que he publicado, combinan el cliente FLEX y el back-end Java junto con el servidor BlazeDS en el mismo proyecto. Si se quiere tener por separado el servidor BlazeDS, bastará con desplegar el war de blazeDS en el Tomcat, o si no tenemos el .war, basta con copiar el contenido de la carpeta “tomcat”  en la carpeta “webapps” del Apache Tomcat y arrancarlo.

Dentro del servidor BlazeDS recién instalado dentro del Tomcat, en la carpeta WEB-INF/…/classes dejaremos los .class de java que trabajen con los objetos remotos que soliciteÇ/envíe FLEX, creando la misma estructura de carpetas que tienen en su definición de package. Por último se definen los “destination” en en WEB-INF/Flex/remoting-config.xml apuntando a esas clases y con un id, y esos servlets ya están listos para trabajar en remoto con FLEX.

.NET (1)
AIR (1)
ANDROID (2)
evitarDolorCabeza(); (1)
FLEX (10)
Flex Data Access (9)
GAMES (2)
Java (6)
JDBC (3)
Maven (1)
Mobile (1)
Servidores (8)
Spring (4)
Uncategorized (1)

WP Cumulus Flash tag cloud by Roy Tanck requires Flash Player 9 or better.