Warning: Constant ABSPATH already defined in /customers/e/7/0/florian-oeser.de/httpd.www/wordpress/wp-config.php on line 28 Warning: Cannot modify header information - headers already sent by (output started at /customers/e/7/0/florian-oeser.de/httpd.www/wordpress/wp-config.php:28) in /customers/e/7/0/florian-oeser.de/httpd.www/wordpress/wp-includes/feed-rss2.php on line 8 Flash/Flex/AS3 – Development-Blog von Florian Oeser http://www.florian-oeser.de "Die Wissenschaft hat keine Heimat, denn das Wissen gehört der Menschheit und ist ein Leuchtturm, der die Welt erhellt." (Louis Pasteur) Mon, 15 Dec 2008 16:44:05 +0000 de-DE hourly 1 https://wordpress.org/?v=6.0.8 HowTo: FDS-Tomcat + Datamanagement + Hibernate http://www.florian-oeser.de/2008/07/08/howto-fds-tomcat-datamanagement-hibernate/ http://www.florian-oeser.de/2008/07/08/howto-fds-tomcat-datamanagement-hibernate/#comments Tue, 08 Jul 2008 12:14:19 +0000 http://www.florian-oeser.de/?p=51 Einleitung

Das wird das letzte HowTo rund um die RIA-Entwicklung mit Flex, den LCDS und Hibernate auf den beiden Servern BlazeDS und FDS-Tomcat. Bisher haben wir gesehen wie man diese auf einem Linuxsystem installiert, mit Servlets Datenbankoperationen handelt und wie man dann mit Hibernate und und Flex ein Front- und Backend entwickeln kann.

Bis jetzt haben wir die Daten an den Client per RPC(HTTP Service und RemoteObject) gesendet und empfangen. Jetzt benutzen wir das wohl innovativste Element der Live Circle Data Services. Den synchronen Remote-Zugriff. Im Gegensatz dazu verlief alles bis jetzt asynchron und musste über das entspechende Result-Event gelöst werden. Jetzt werden Änderungen an den Daten zwischem dem Server und (wahlweise) allen Clients instant aktualisiert. Das heißt wenn ein Client Daten ändert wird automatisch das Backend informiert, welches sich sofort um die persistente Speicherung durch Hibernate kümmert und alle anderen Clients über die entsprechenden Änderungen informiert(push).

Wir verwenden dazu nur noch den FDS-Tomcat da dieser Service nicht im BlazeDS integriert ist. Sicherlich würde sich das nachrüsten lassen, jedoch habe ich mich damit nicht beschäftigt. Prinziepell halte ich mich an das Sample 8: Data Management Services aus dem Testdrive des FDS-Tomcat’s. Es kann also nicht schaden sich die Sachen dazu und das direkte Tutorial anzuschauen, da ich lediglich den bekannten HibernateHandler erweitere und nicht weiter auf Konfigurationen eingehe.

Im Übrigen benutzen wir auch nicht den Hibernate Assembler/Adapter sondern bleiben bei der direkten Hibernate-Implementierung. Falls ihr euch für diesen Assembler interessiert gibt es bei den Testdrive-Tutorials ebenfalls ein Beispiel. Das ist sehr ähnlich dem Sample 8 benutzt dann aber Hibernate.

Um die Umsetzung nachvollziehen zu können, möchte ich euch wieder gleich den Source geben. Darin erhalten ist dann ebenfalls gleich wieder ein SQL-Dump.

Die Umsetzung

Das Backend

Für die Umsetzung bedienen wir uns wieder der Stream-Tabelle aus dem Servlets-HowTo.

Nun werden wir ähnlich wie im Sample 8 die Tabelle auslesen und in ein DataGrid schreiben. Es wird nicht viel Arbeit, da wir nur eine neue Klasse einführen werden und ansonsten nur vorhandene Sachen erweitern.

Anfangen möchte ich mit dem sogenannten Streamassembler. Dieser implemtiert den AbstractAssembler aus dem LCDS. Das heißt wir müssen die Methoden fill(), getItem(), update() und deleteItem() überschreiben. Der Assembler ist sehr wichtig, da seine Methoden aufgerufen werden wenn es zu Änderungen am Tabelleninhalt kommt. Das heißt unsere Client arbeitet nicht mehr direkt mit dem HibernateAssembler. Das macht jetzt der Streamassembler direkt in den überschriebenen Funktionen. Da zum Aktualisieren der Daten aber erstmal nur fill() und update() wichtig ist, beschränke ich mich auf deren Implementierung. Die anderen könnt ihr sicher alleine implementieren 🙂

package flex.radioSiTY;

import java.util.List;
import java.util.Collection;
import java.util.Map;

import flex.data.DataSyncException;
import flex.data.assemblers.AbstractAssembler;

public class StreamAssembler extends AbstractAssembler {

	public Collection fill(List fillArgs) {
		HibernateHandler service = new HibernateHandler();
		return service.getStreams();
	}

	/*public Object getItem(Map identity) {
		
		}
	}*/

	public void createItem(Object item) {
		
	}

	public void updateItem(Object newVersion, Object prevVersion, List changes) {
		HibernateHandler service = new HibernateHandler();
		service.update((Stream) newVersion);		
	}

	public void deleteItem(Object item) {
		
	}
	
}

Nun kommen die Änderungen an unserem bekannten HibernateHandler. Diesem fügen wir die zwei neuen Funktionen, die der StreamAssembler benötigt, hinzu:

public List getStreams() throws DAOException {

		List list = new ArrayList();
		Session sess = null;
		Transaction trx = null;

		try {
			sess = sessionFactory.openSession();
			trx = sess.beginTransaction();
			System.out.println("\nStreams:");
			List streams = sess.createQuery("from Stream").list();
			for (int i = 0; i < streams.size(); i++) {
				Stream stream = (Stream) streams.get(i);
				list.add(new Stream(stream.getId(), stream
						.getUrl(), stream.getHomepage(), stream.getName(),
						stream.getgenreId(), stream.getImage()));
			}
				trx.commit();
			} catch (HibernateException ex) {
				if (trx != null)
					try {
						trx.rollback();
					} catch (HibernateException exRb) {
					}
				throw new RuntimeException(ex.getMessage());
			} finally {
				try {
					if (sess != null)
						sess.close();
				} catch (Exception exCl) {
				}
			}
		return list;

	}
	
	public void update(Stream stream) throws DAOException {

		Session sess = null;
		Transaction trx = null;
		
		try {
			sess = sessionFactory.openSession();
			trx = sess.beginTransaction();
			
			sess.update(stream);
			trx.commit();
		} catch (HibernateException ex) {
			if (trx != null)
				try {
					trx.rollback();
				} catch (HibernateException exRb) {
					System.out.println(exRb.toString());
				}
			throw new RuntimeException(ex.getMessage());
		} finally {
			try {
				if (sess != null)
					sess.close();
			} catch (Exception exCl) {
			}
		}

	}
&#91;/sourcecode&#93;

Damit das ganze funktionieren kann brauchen wir in der Streamklasse noch zwei Konstruktoren:

&#91;sourcecode language='java'&#93;
package flex.radioSiTY;

import java.util.*;

public class Stream 
{
  private int    id;
  private String url;
  private String homepage;
  private String name;
  private int genreId;
  private String image;
  private Set    user     = new HashSet();
  private Set    comments = new HashSet();
  
  public Stream() {name = "test"; }
  
  public Stream(int id, String url, String homepage, String name, int genreId, String image) {
		this.id = id;
		this.url = url;
		this.homepage = homepage;
		this.image = image;
		this.name = name;
		this.genreId = genreId;		
	}
  
  public Stream(Stream stream) {
		this.id = stream.getId();
		this.url = stream.getUrl();
		this.homepage = stream.getHomepage();
		this.image = stream.getImage();
		this.name = stream.getName();
		this.genreId = stream.getgenreId();	
	}

  public int    getId()         { return id; }
  public String getUrl()    { return url; }
  public String getHomepage()    { return homepage; }
  public String getName()      { return name; }
  public int getgenreId()    { return genreId; }
  public String getImage()      { return image; }
  public Set    getUser()     { return user; }
  public Set    getComments() { return comments; }

  public void setId(         int id         ) { this.id = id; }
  public void setUrl( String url    ) { this.url = url; }
  public void setHomepage( String homepage    ) { this.homepage = homepage; }
  public void setName( String name    ) { this.name = name; }
  public void setgenreId ( int genre    ) { this.genreId = genre; }
  public void setImage(   String image      ) { this.image = image; }
  public void setUser(     Set user     ) { this.user = user; }
  public void setComments( Set comments ) { this.comments = comments; }
}
&#91;/sourcecode&#93;

Das waren jetzt auch schon alle Änderungen die das Backend betreffen. 

<h5>Das Frontend</h5>

Für das Frontend erstellen wir einfach ein Datagrid, welches nun durch den StreamAssembler über die Methode fill() gefüllt wird. Das Datagrid liest dann die Collection automatisch ein. Ganz wichtig ist jetzt hier das wir den DataService und nicht mehr das RemoteObject benutzen. Hier der Source:


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" backgroundColor="#FFFFFF" viewSourceURL="srcview/index.html">
	
	<mx:ArrayCollection id="streams"/> 
	<mx:DataService id="ds" destination="stream"/>
	<Stream/>
	
	<mx:DataGrid dataProvider="{streams}" editable="true" width="100%" height="100%">
		<mx:columns>
			<mx:DataGridColumn dataField="url" headerText="Url"/>
			<mx:DataGridColumn dataField="homepage" headerText="Homepage"/>
			<mx:DataGridColumn dataField="name" headerText="Name"/>
			<mx:DataGridColumn dataField="genreId" headerText="Genre"/>
			<mx:DataGridColumn dataField="image" headerText="Image"/>
		</mx:columns>
	</mx:DataGrid>
	
	<mx:Button label="Get Data" click="ds.fill(streams)"/> 
	
</mx:Application>

Die Methode updateItem() des StreamAssemblers muss nicht aufgerufen werden, da diese bei Änderungen an der Tabelle automatisch aufgerufen wird 🙂

Damit das ganze überhaupt funktionieren kann müssen wir natürlich noch die Destination für den DataService anlegen. Das passiert ähnlich wie bei den RemoteObjects. Nur benutzen wir jetzt nicht mehr die remoting-config.xml sondern die datamanagement-config.xml!Einfach folgenden Eintrag hinzufügen:

<destination id="stream">

        <adapter ref="java-dao" />

        <properties>
            <source>flex.radioSiTY.StreamAssembler</source>
            <scope>application</scope>

            <metadata>
                <identity property="id"/>
            </metadata>

            <network>
                <session-timeout>20</session-timeout>
                <paging enabled="false" pageSize="10" />
                <throttle-inbound policy="ERROR" max-frequency="500"/>
                <throttle-outbound policy="REPLACE" max-frequency="500"/>
            </network>
        </properties>
    </destination>

Conclusion

So das wars dann auch schon. Öffnet die Tabelle einfach mal in zwei Tab’s und ändert in der einen etwas. Siehe da die andere Tabelle wird instant aktualisiert 🙂

Leider habe ich mich nicht mit den verschiedenen Einstellungsmöglichkeiten was das Datamanagement betrifft auseinandersetzten können. Da gibt es einige Sachen die sich konfigurieren lassen. Zum Beispiel auf welchen Clients überhaupt aktualisiert werden soll etc. Dazu findet ihr aber in dem FDMS-Tutorial wenn ich micht recht entsinne einiges.

So das wars für diese How-To Reihe. Ich hoffe bei euch hat alles geklappt und hattet damit genausoviel Spass wie ich 🙂

Bei Fragen und Anregungen könnt ihr mir wie immer mailen oder ein Kommentar hinterlassen!

]]>
http://www.florian-oeser.de/2008/07/08/howto-fds-tomcat-datamanagement-hibernate/feed/ 1
HowTo: BlazeDS/FDS-Tomcat + Flex + Hibernate + MySQL http://www.florian-oeser.de/2008/06/07/howto-blazedsfds-tomcat-flex-hibernate-mysql/ http://www.florian-oeser.de/2008/06/07/howto-blazedsfds-tomcat-flex-hibernate-mysql/#respond Sat, 07 Jun 2008 12:41:19 +0000 http://www.florian-oeser.de/?p=41 Einleitung

In diesem HowTo möchte ich euch zeigen wie man mit den beiden Servern eine persistente Datenhaltung realisiert. Dabei werden wir mit MySQL/JDBC und die LiveCycle Data Services (kurz LCDS) arbeiten. Die LCDS sind in beiden Servern bereits integriert. Wir werden alle Datenkommunikationen per RemoteObject betreiben. Ich werde nicht auf Basics eingehen, deshalb ist es empfehlenswert die Testdrive Tutorials schon einmal angeschaut und nachvollzogen zu haben. Ich werde auch nicht auf die Installation der beiden Server eingehen. Wie man

com.mysql.jdbc.Driverbeide auf einem Linux-System installiert habe ich in diesem HowTo bereits gezeigt.

Am Ende des Tutorials haben wir als Frontend eine minimale Flexanwendung(mxml-Anwendung) geschrieben, die über Data Access Objects (DAO) Daten in die Datenbank schreibt und auch ausliest. Für das HowTo verwende ich Teile aus unserem Projekt radioSiTY.

Gleich vorweg der Source. Da ich nicht alle Klassen und Config’s zeige könnt ihr so besser mitarbeiten. Dort findet ihr auch den SQL-Dump für unsere kleine Datenbank und müsste diese so nicht selbst erstellen 😉

Source (.rar, 271KB)

Vorbereitungen Datenhaltung

In radioSiTY haben wir verschiedene Funktionen mit Hibernate und RPC umgesetzt. Für dieses HowTo modellieren wir die Kommentar- und Streamfunktionen. Das heißt konkret das wir folgende Funktionen implementieren:

  • addStream()
  • addComment()
  • showComments()
  • showStreams()

Da zu jedem Kommentar auch ein Benutzer gehört dürfen wir natürlich eine User-Tabelle nicht vergessen. Unsere Datenbank sieht also wie folgt aus:

howto_datamodel

Damit ihr das Tutorial möglichst schnell nachvollziehen könnt habe ich hier mal den SQL-Dump. Denn braucht ihr nur mit folgenden Befehl in die Datenbank einschleusen:

mysql.exe -u username -p radiositiy_db1 < db.sql

Die Datenbank muss vorher natürlich angelegt sein. Auch der username muss entsprechend angepasst werden.

Die Entity-Klassen in Java haben schließlich folgende Struktur:

howto_classmodel

Wir haben zum einen einen Hibernatehandler der Hibernate ansich initialisiert und alle Funktionen hält. Zum Anderen haben wir die Klassen User, Comments und Stream. Diese Klassen stellen das DAO dar und haben lediglich Getter- und SetterMethoden. Aus Gründen der Übersichtlichkeit habe ich aber nicht alle Methoden aufgeführt.

Vorbereitung zu Hibernate

Hibernate braucht um Arbeiten zu können die Verbindungsangaben zur Datenbank. Desweiteren muss Hibernate auch die einzelnen Tabellen und deren Felder kennen. Diese Angaben macht man in sogenannten Mappingfiles(DAO<->Tabelle) im XML-Format. Zunächst legen wir aber erstmal die Konfigurationsdatei, mit dem Namen hibernate.cfg.xml, für Hibernate an:

<?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>

<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/radiositiy_db1</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>

<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>

<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>

<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>

<property name="transaction.factory_class">
org.hibernate.transaction.JDBCTransactionFactory
</property>

<!-- Disable the second-level cache  -->
<property name="cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>        <!-- Echo all executed SQL to stdout -->

<property name="show_sql">true</property>

<!-- Load the database table mapping file -->
<mapping resource="Product.hbm.xml"/>
<mapping resource="Stream.hbm.xml"/>
<mapping resource="User.hbm.xml"/>
<mapping resource="comments.hbm.xml"/>
</session-factory>

</hibernate-configuration>

Die erste property ist die Treiberangabe. In unserem Fall wäre das MySQL. Hier könnte man dann auch andere Treiber, wie etwa für HSQL, angeben. Die nächsten drei property Angaben sind selbsterklärend und benötigen lediglich eine Anpassung an eure Datenbank. Wichtig ist weiterhin das man bei der dialect property den MySQLDialect wählt. Analog zum Treiber sind auch hier andere Angaben möglich. Auf die property show_sql komme ich bei der Implementierung des HibernateHandlers noch einmal zu sprechen. Sehr wichtig sind ganz unten die mapping resource’s. Das sind unsere oben angesprochenen Mappingfiles. Sie enthalten im Namen immer *.hbm.

Wobei wir auch schon beim Thema wären: Die Implementierung dieser Files. Aus Gründen der Übersichtlichkeit poste ich nur die Stream.hbm.xml.:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="flex.radioSiTY.Stream" table="tbl_streams">
<id name="id" column="id" type="integer">
<generator class="native"/>
</id>
<property name="url"  column="fld_url"  type="string"/>
<property name="homepage"   column="fld_homepage"   type="string"/>
<property name="name"   column="fld_name"   type="string" />
<property name="genreId" column="genre_id" type="integer"/>
<property name="image" column="fld_image" type="string"/>
<set name="user" table="tbl_stream_comments" lazy="true" inverse="true" >
<key column="stream_id"/>
<many-to-many class="flex.radioSiTY.User" column="id"/>
</set>
</class>
</hibernate-mapping>

Wie man sieht steht in jeder Mappingfile die Klasse/Tabelle die gemappt werden soll. Danach folgen die Angaben zu den einzelnen Spalten. Der type ist immer auf die Javadatentypen bezogen und nicht auf die MySQL-Typen. Ihr solltet auch immer zweimal schauen ob der Spaltenname mit dem in der Datenbank übereinstimmt. Zu guter letzt muss dann noch in einem set die Beziehung zu der anderen Tabelle hergestellt werden. Wichtig zu erwähnen wären noch die many-to-one Relationen in der comments.hbm.xml. Diese Angaben sind essentiel da eine Kommentar schließlich die Angaben beinhalten, von welchen Benutzer, zu welchen Stream ein Kommentar geschrieben wurde.

Alle *.hbm’s und die hibernate.cfg.xml kommen direkt unter das \WEB-INF\classes Verzeichniss.

Ich möchte an dieser Stelle noch die Beispielanwendung zu Hibernate von Thorsten Horn erwähnen. Das ist ebenfalls ein schönes Tutorial und geht genauer auf die Sachen rund um Hibernate ein. Jedoch ohne Flex-Frontend und mit HSQL 😉

Wenn ihr den FDS-Tomcat verwendet könnt ihr getrost zum nächsten Kapitel springen. Falls ihr den BlazeDS verwendet müssen wir noch ein paar Hibernate *.jar’s kopieren. Dazu müsst ihr aber zuerst den sogenannten Hibernate Core herunterladen. Das Archiv entpacken und folgenden *.jar’s nach BlazeDS\tomcat\webapps\samples\WEB-INF\lib kopieren: asm.jar, cglib-2.1.3.jar, checkstyle-all.jar, commos-collections-2.1.1.jar, dom4j-1.6.1.jar, hibernate3.jar, jta.jar und die log4j-1.2.11.jar.

Das wars dann auch schon 😀

Implementierung Backend (Hibernatehandler und DAO’s)

So jetzt gehts ans Eingemacht. Zunächst die Entity-Klassen. Auch hier poste ich nur die Stream.java, da die Anderen zu 90% gleich sind.

package flex.radioSiTY;

import java.util.*;

public class Stream 
{
  private int    id;
  private String url;
  private String homepage;
  private String name;
  private int genreId;
  private String image;
  private Set    user     = new HashSet();
  private Set    comments = new HashSet();
  
  public Stream() { }
  

  public int    getId()         { return id; }
  public String getUrl()    { return url; }
  public String getHomepage()    { return homepage; }
  public String getName()      { return name; }
  public int getgenreId()    { return genreId; }
  public String getImage()      { return image; }
  public Set    getUser()     { return user; }
  public Set    getComments() { return comments; }

  public void setId(         int id         ) { this.id = id; }
  public void setUrl( String url    ) { this.url = url; }
  public void setHomepage( String homepage    ) { this.homepage = homepage; }
  public void setName( String name    ) { this.name = name; }
  public void setgenreId ( int genre    ) { this.genreId = genre; }
  public void setImage(   String image      ) { this.image = image; }
  public void setUser(     Set user     ) { this.user = user; }
  public void setComments( Set comments ) { this.comments = comments; }
}


[/Sourcecode]

Jetzt unser <em>HibernateHandler</em>:

/*!
 * @brief Hibernate Handler
 * 
 * Der HibernateHandler stellt die Schicht zwischen der Flexanwendung und der Datenbank dar. Hibernate ist ein 
 * objektorientiertes Persistence Framework. Das heißt alle Daten liegen als Objekte vor und werden auch so in die Datenbank geschrieben und gelesen.
 * Aufgabe des Handlers ist es die Verbindung zur Datenbank herzustellen, eine Session und Transaction aufzubauen.
 *  
 * Wichtig: Hibernate jar's müssen dem BuildPath hinzugefügt werden!
 */

package flex.radioSiTY;

import java.util.*;

import org.hibernate.*;
import org.hibernate.cfg.Configuration;

import java.security.MessageDigest;
import java.sql.SQLException;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HibernateHandler {
	public SessionFactory sessionFactory = null;

	// public Session sess = null;
	// public Transaction trx = null;

	// ! @brief Hibernate wird im Konstruktor initialisiert
	public HibernateHandler() {
		/*
		 * Die Konfiguration für die Datenbankverbindung und das Mapping der
		 * einzelnen Tabellen liegt in der 'hibernate.conf'
		 */
		if (sessionFactory == null) {
			try {
				System.out
						.println("------------------------------------------------------");
				System.out.println("Initializing Hibernate");
				sessionFactory = new Configuration().configure()
						.buildSessionFactory();
				System.out.println("Finished Initializing Hibernate");
				System.out
						.println("------------------------------------------------------");
			} catch (HibernateException ex) {
				ex.printStackTrace();
				System.exit(5);
			}
		}
	}

	public static void main(String[] args) {

		/*
		 * ! Dies sind lediglich Tests die man lokal durchführen kann. Der
		 * Output erfolgt hier über die Console. Die eigentlichen Aufrufe der
		 * Mehtoden erfolgt durch Flex über RPC. Somit ist die main() eigentlich
		 * hinfällig und dient lediglich weiteren lokalen Tests.
		 */

		 HibernateHandler handler = new HibernateHandler();
		// String test = new String();
		// handler.showCommentsFromStream(78, false);
		// Date date = new Date(1922,110,23);
		// handler.updateUser(25, "Hans Test", "nickname" , "egal",
		// "test@test.de", date);
		// handler.addStream("http://test.de", "http://test.de", "testStream",
		// 5, "C:/test2.image");
		// egal = handler.showUsers();
		// egal =handler.showStreams();
		// handler.showComments();
		// System.out.println(test);
		// User user = new User();
		// Stream stream = new Stream();
		// user = handler.getUser(25);
		// stream = handler.getStream(88);
		// handler.addComments(6, 9, "test4mitch", date, 0);
		// System.out.println(user.getName() );
		// System.out.println(stream.getName());
		
		 //LCDS
		 /*List testListe = new ArrayList(handler.getStreams());
		 for(int i = 0; i< testListe.size(); i++) System.out.println((Stream)testListe.get(i));*/
		 
		 /*Stream testStream = new Stream(handler.getStream(16));		
		 testStream.setName("test me");		
		 handler.update(testStream);*/
		 
	}

	
	/*
	 * ! @brief Diese Methode fügt eine Stream in die DB ein. Verwendet wird sie
	 * wenn ein Benutzer einen Stream hinzufügt.
	 */
	public void addStream(String url, String homepage, String name,
			int genreId, String image) {
		Session sess = null;
		Transaction trx = null;
		try {
			sess = sessionFactory.openSession();
			trx = sess.beginTransaction();
			Stream stream = new Stream();
			// stream.setId(id); wird automatisch inkrementiert
			stream.setUrl(url);
			stream.setHomepage(homepage);
			stream.setName(name);
			stream.setgenreId(genreId);
			stream.setImage(image);

			sess.save(stream);
			trx.commit();
		} catch (HibernateException ex) {
			if (trx != null)
				try {
					trx.rollback();
				} catch (HibernateException exRb) {
				}
			throw new RuntimeException(ex.getMessage());
		} finally {
			try {
				if (sess != null)
					sess.close();
			} catch (Exception exCl) {
			}
		}
	}

	/*
	 * ! @brief Diese Methode fügt ein Kommentar in die DB ein. Verwendet wird
	 * sie wenn ein Benutzer ein Kommentar hinzufügt.
	 */
	public void addComment(int userId, int streamId, String text, int blocked) {
		System.out.println("\n\nInit add!\n");

		Date date = new Date();

		System.out.println("Comment in DB speichern!!!!!\n");
		Session sess = null;
		Transaction trx = null;

		try {
			sess = sessionFactory.openSession();
			trx = sess.beginTransaction();
			Comments comment = new Comments();
			// comment.setId(id); wird automatisch inkrementiert
			comment.setText(text);
			System.out.println(text + "\n");
			comment.setBlocked(blocked);
			System.out.println(blocked + "\n");
			comment.setDate(date);
			System.out.println(date + "\n");
			comment.setUser(getUser(userId));
			comment.setStream(getStream(streamId));

			sess.save(comment);
			System.out.println("Now added!\n\n");
			trx.commit();
		} catch (HibernateException ex) {
			if (trx != null)
				try {
					trx.rollback();
				} catch (HibernateException exRb) {
				}
			throw new RuntimeException(ex.getMessage());
		} finally {
			try {
				if (sess != null)
					sess.close();
			} catch (Exception exCl) {
			}
		}
	}

	/*
	 * ! @brief Die Methode gibt ein Userobjekt nach ID zurück.
	 * 
	 * Wird von addComment() verwendet @param userId ID des Benutzers @return
	 * User-Objekt
	 */
	public User getUser(int userId) {
		Session sess = null;
		Transaction trx = null;

		User user = new User();

		try {
			sess = sessionFactory.openSession();
			trx = sess.beginTransaction();
			System.out.println("\nUser zu Id:" + userId);

			String hql = new String(
					"select user from User as user where user.id = :userId");
			Query query = sess.createQuery(hql);
			query.setInteger("userId", userId);
			Iterator itr = query.iterate();
			while (itr.hasNext()) {
				user = (User) itr.next();
			}
			trx.commit();
		} catch (HibernateException ex) {
			if (trx != null)
				try {
					trx.rollback();
				} catch (HibernateException exRb) {
				}
			throw new RuntimeException(ex.getMessage());
		} finally {
			try {
				if (sess != null)
					sess.close();
			} catch (Exception exCl) {
			}
		}
		return user;
	}

	/*
	 * ! @brief Die Methode gibt ein Streamobjekt nach ID zurück. Wird von
	 * addComment() verwendet @param streamId ID des Streams @return
	 * Stream-Objekt
	 */
	public Stream getStream(int streamId) {
		Session sess = null;
		Transaction trx = null;
		Stream stream = new Stream();

		try {
			sess = sessionFactory.openSession();
			trx = sess.beginTransaction();
			System.out.println("\nStream zu Id:" + streamId);

			String hql = new String(
					"select stream from Stream as stream where stream.id = :streamId");
			Query query = sess.createQuery(hql);
			query.setInteger("streamId", streamId);
			Iterator itr = query.iterate();
			while (itr.hasNext()) {
				stream = (Stream) itr.next();
			}
			trx.commit();
		} catch (HibernateException ex) {
			if (trx != null)
				try {
					trx.rollback();
				} catch (HibernateException exRb) {
				}
			throw new RuntimeException(ex.getMessage());
		} finally {
			try {
				if (sess != null)
					sess.close();
			} catch (Exception exCl) {
			}
		}
		return stream;
	}

	/*
	 * ! @brief Diese Methode gibt die verfügbaren Kommentare aus.
	 * 
	 * Wahlweise nach User oder Stream @param id Angabe des Streams oder des
	 * Users @param searchUser Angabe ob nach Kommentaren eines Users(true) oder
	 * nach Kommentaren zu einem Stream gesucht wird @return Gibt das Ergebniss
	 * als XML-String zurück
	 */
	public String showComments(int id, boolean searchUser) {
		Session sess = null;
		Transaction trx = null;
		StringBuffer output = new StringBuffer();

		try {
			sess = sessionFactory.openSession();
			trx = sess.beginTransaction();
			String hql = new String();
			if (!searchUser) {
				hql = "select comment from Comments as comment where comment.stream = :id order by date asc";
			} else {
				hql = "select comment from Comments as comment where comment.user = :id";
			}

			Query query = sess.createQuery(hql);
			query.setInteger("id", id);
			Iterator itr = query.iterate();

			System.out.println("\n\nComments als XML ausgeben!!!!!\n\n");

			output.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			output.append("<comments>");

			while (itr.hasNext()) {
				Comments comment = (Comments) itr.next();
				output.append("<comment>");
				output.append("\t<text>" + comment.getText() + "</text>");
				output.append("\t<user>" + comment.getUser().getUsername()
						+ "</user>");
				output.append("\t<date>" + comment.getDate().toString()
						+ "</date>");
				output.append("</comment>");
			}

			output.append("</comments>");
			trx.commit();
		} catch (HibernateException ex) {
			if (trx != null)
				try {
					trx.rollback();
				} catch (HibernateException exRb) {
				}
			throw new RuntimeException(ex.getMessage());
		} finally {
			try {
				if (sess != null)
					sess.close();
			} catch (Exception exCl) {
			}
		}
		String string = new String(output);

		// HttpServletResponse response;
		// response.setContentType("text/html");

		return string;
	}

	// ! @brief Diese Methode gibt alle Kommentare als String zurück
	public String showComments() {
		Session sess = null;
		Transaction trx = null;

		StringBuffer output = new StringBuffer();

		try {
			sess = sessionFactory.openSession();
			trx = sess.beginTransaction();
			System.out.println("\nAlle Kommentare:");
			List comments = sess.createQuery("from Comments").list();
			for (int i = 0; i < comments.size(); i++) {
				Comments comment = (Comments) comments.get(i);

				output.append("Commment: " + comment.getText());
				System.out.println("Commment: " + comment.getText()
						+ "\nvon User: " + comment.getUser().getUsername()
						+ "\nStreamname:" + comment.getStream().getName());

			}
			trx.commit();
		} catch (HibernateException ex) {
			if (trx != null)
				try {
					trx.rollback();
				} catch (HibernateException exRb) {
				}
			throw new RuntimeException(ex.getMessage());
		} finally {
			try {
				if (sess != null)
					sess.close();
			} catch (Exception exCl) {
			}
		}
		String string = new String(output);
		return string;
	}

	// ! @brief Diese Methode gibt alle Streams als String zurück
	public String showStreams() {
		Session sess = null;
		Transaction trx = null;

		StringBuffer output = new StringBuffer();

		try {
			sess = sessionFactory.openSession();
			trx = sess.beginTransaction();
			System.out.println("\nStreams:");
			List streams = sess.createQuery("from Stream").list();
			for (int i = 0; i < streams.size(); i++) {
				Stream stream = (Stream) streams.get(i);

				output.append("Streams: " + stream.getName());
				System.out.println("GenreId:  " + stream.getgenreId()
						+ "\nName: " + stream.getName() + "\nHomepage: "
						+ stream.getHomepage() + "\nUrl: " + stream.getUrl()
						+ "\nImage: " + stream.getImage());
			}

			trx.commit();
		} catch (HibernateException ex) {
			if (trx != null)
				try {
					trx.rollback();
				} catch (HibernateException exRb) {
				}
			throw new RuntimeException(ex.getMessage());
		} finally {
			try {
				if (sess != null)
					sess.close();
			} catch (Exception exCl) {
			}
		}
		String string = new String(output);
		return string;
	}

	// ! @brief Diese Methode gibt alle User als String zurück
	public String showUsers() {
		Session sess = null;
		Transaction trx = null;

		StringBuffer output = new StringBuffer();

		try {
			sess = sessionFactory.openSession();
			trx = sess.beginTransaction();
			List users = sess.createQuery("from User").list();
			for (int i = 0; i < users.size(); i++) {
				User user = (User) users.get(i);

				output.append("User : " + user.getName());
				System.out.println("Name:  " + user.getName() + " Username: "
						+ user.getUsername() + " Alter: " + user.getBirthday());

			}
			trx.commit();
		} catch (HibernateException ex) {
			if (trx != null)
				try {
					trx.rollback();
				} catch (HibernateException exRb) {
				}
			throw new RuntimeException(ex.getMessage());
		} finally {
			try {
				if (sess != null)
					sess.close();
			} catch (Exception exCl) {
			}
		}
		String string = new String(output);
		return string;
	}
	
	
}
&#91;/sourcecode&#93;
Okay ersmal eine Menge Source. Wie versprochen sind alle Methoden die wir brauchen aufgeführt. Es sind aber noch zwei weitere hinzugekommen. Nämlich <em>getUser()</em> und <em>getStream()</em>, die für die Funktion <em>addComment()</em>, die dann den jeweiligen User und Stream zurückgeben. Wie ihr seht geben unsere Funktionen bis auf <em>showStreams()</em> immer XML-Strings zurück. Das hat den Grund das wir in <em>radioSiTY</em> diese Strings in ein DataGrid schreiben werden ;-)

Im Source findet ihr übrigens noch die Funktion <em>updateUser()</em>. Dort seht ihr wie man mit Hibernate eine Tabelle updatet.

Erwähnenswert wäre noch die main(). Dort seht ihr die auskommentierten Funktionsaufrufe. Das waren unsere Testmethoden bevor wir überhaupt an das Frontend gegangen sind. Man kann nämlich diese Anwendung auch als Konsolenanwendung starten. Dazu müsst ich nur wieder in die einzelnen Funktionen die Ausgabe über <em>System.out.println()</em> gestalten ansatt einen String zurückzugeben (siehe <em>showStreams()</em>). Ich errinner mich gerade das ich ja nochmal auf den SQL-Output aus der Hibernate-Konfigurationsdatei zu sprechen kommen wollte. Dadurch das wir den Wert auf <em>true</em> gesetzt hatten, sehen wir jetzt die SQL Ausgabe in der Konsole. Das betrifft dann auch die Ausgaben auf der Konsole von BlazeDS/FDS-Tomcat. Sehr nützlich ;-)

Im Übrigen seht ihr, dass alle Querys in <em>HQL </em>geschrieben sind. Das ist die <em>Hibernate Query Language</em> und muss benutzt werden. Es ist also kein normales <em>SQL</em> möglich. Es ist übrigens sehr wichtig das ihr alle <em>Hibernate *.jar's</em> zu dem <em>Java Build Path</em> hinzufügt, da sich ansonsten das Projekt nicht kompilieren lässt.

Jetzt legt ihr unter dem Ordner <em>\WEB-INF\classes\flex</em> das Verzeichniss radioSiTY an. Dort hinein kopiert ihr die kompilierten <em>DAO-Klassen</em> und den <em>HibernateHandler</em>.
<h4>Implementierung Frontend (mxml-Applikation)</h4>
So wir kommen langsam aber sicher zum Ende. Nun ist es nicht mehr viel. Wir schreiben eine ganz kleine Anwendung du die unsere Funktionen nutzt. Nur die <em>addStream()</em> nicht, da diese analog zu <em>addComment()</em> läuft. Aber das seht ihr dann eh selbst im Source.

<a href="http://www.florian-oeser.de/wordpress/wp-content/2008/06/hibernate_mxml.jpg"><img class="aligncenter size-medium wp-image-47" title="hibernate_mxml" src="http://www.florian-oeser.de/wordpress/wp-content/2008/06/hibernate_mxml-300x128.jpg" alt="hibernate_mxml" width="300" height="128" /></a>

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<!&#91;CDATA&#91;

private function checkComments():void {

remoteObject.showComments(78,false);
}

private function addComments() :void {

remoteObject.addComment(userId.text,streamId.text,text.text,blocked.text);
remoteObject.showComments(streamId.text,false);

}

&#93;&#93;>
</mx:Script>
<mx:RemoteObject id="remoteObject" destination="product"/>

<mx:Button x="115" y="58" label="Get Comments" id="getComments" click="checkComments()"/>
<mx:Button x="587" y="58" label="Get Streams" id="getStreams" click="remoteObject.showStreams()"/>
<mx:TextInput x="70" y="345" width="37" id="streamId"/>
<mx:TextInput x="169" y="345" width="31" id="userId"/>
<mx:TextInput x="282" y="345" width="246" id="text"/>
<mx:TextInput x="599" y="345" width="59" id="blocked"/>
<mx:Button x="684" y="345" label="add Comment" id="addComment" click="addComments()"/>
<mx:TextArea x="483" y="109" width="330" height="196" id="txt_getStreams" text="{remoteObject.showStreams.lastResult}" />
<mx:TextArea x="52" y="109" id="txt_getComments" text="{remoteObject.showComments.lastResult}" width="311" height="196"/>
<mx:Label x="10" y="347" text="streamId:"/>
<mx:Label x="115" y="347" text="userId:"/>
<mx:Label x="239" y="347" text="text:"/>
<mx:Label x="537" y="347" text="blocked?"/>

</mx:Application>

Ich denke der Source ist leicht verständlich. Wichtig ist das RemoteObject. Denn das gibt an aus welcher Klasse überhaupt die Methoden aufgerufen werden sollen. Diese Destination muss ähnlich wie bei bei der web.xml in einer Konfigurationsdatei bekannt gegeben werden. Aber dazu komm ich gleich. Weiterhin hätte man die XML-Ausgabe bei den Kommentaren auch in ein DataGrid lesen können.

Da das RemoteObject teil der LCDS ist muss man bei der Projekterstellung noch ein paar Sachen beachten. So müsst ihr unter Server technology die J2EE angeben. Der Haken bei Use remote object access service muss natürlich gesetzt sein. Im nächsten Fenster sind auch noch ein paar Einstellungen zu treffen. Hier muss ein Server ausgewählt werden, auf dem die Applikation kompiliert und ausgeführt werden soll. Wichtig dabei ist das der Server vor dem validieren gestartet ist. Ich zeige euch die Einstellungen für den BlazeDS und für den FDS-Tomcat:

hibernate_fds_conf

hibernate_blaze_conf

Es ist übrigens sehr wichtig auf dem Server zu kompilieren, da es ansonsten zu Fehlern kommt das die RemoteObject-Klasse nicht gefunden wird(in userem Fall der HibernateHandler). Das äussert sich dann in Can’t find Destination Fehlern.

Kommen wir zum letzten Schritt. Wir müssen die Destination noch angeben. Wenn man mit RemoteObject arbeitet findet diese Angabe in der remoting-config.xml unter \WEB-INF\flex statt. Analog zu dem Beispieleintrag fügen also folgendes ein:

<destination id="product">
<properties>
<source>flex.radioSiTY.HibernateHandler</source>
</properties>
</destination>

Jetzt nur noch in Flex das Projekt starten und staunen 😀

Conclusion

Dieses HowTo war recht umfangreich aber ich denke es hat sich gelohnt. Habt ihr alles umgesetzt habt ihr eine gute Basis um eigene Projekt mit Flex und Hibernate zu realisieren. Ich werde bei Gelegenheit die eine oder andere Sache vielleicht noch ein wenig ausführlicher beschreiben. Auch hier noch einmal der Link zum Tutorial von Thorsten Horn, da er wie gesagt die Sachen rund um persistente Datenhaltung, Hibernate und Debugging sehr viel genauer beschreibt.

Ich hoffe ich habe nix vergessen oder übersehen. Bei Fragen oder Anregungen könnt ihr mir wie immer mailen oder ein Kommentar hinterlassen. In dem Sinne viel Erfolg 😀

]]>
http://www.florian-oeser.de/2008/06/07/howto-blazedsfds-tomcat-flex-hibernate-mysql/feed/ 0
Projekt: radioSiTY http://www.florian-oeser.de/2008/06/06/projekt-radiosity/ http://www.florian-oeser.de/2008/06/06/projekt-radiosity/#comments Fri, 06 Jun 2008 15:02:16 +0000 http://www.florian-oeser.de/?p=29 Einleitung

Projekt radioSiTY bezeichnet das 2. größere Projekt was von uns während des Studiums konzipiert und erstellt wurde. Dabei handelt es sich um eine Web-Stream-Plattform, die während des 4. Semesters in der Veranstaltung Multi-Media Engineering 2 entwickelt wurde.
Zunächst ersteinmal zwei Bilder, damit ihr eine Vorstellung von der GUI bekommt.

radio1

radio2

Die Anwendung

Mit dieser Anwendung ist es möglich AOL- und Shoutcastsstreams zu hören. Zu jedem Sender kann man sich aktuelle Informationen über den Sender selbst, den Song der gerade gespielt wird und noch viele andere Sachen anschauen. Es ist weiterhin möglich die Sender zu bewerten und zu kommentieren. Dies ist aber erst möglich sobald man sich erfolgreich registriert hat. Genauere Informationen und noch mehr Bilder findet ihr auf dem Blog meines Mitentwicklers Michael Palmer.

Die Applikation ist unter folgender URL zu finden: http://62.75.209.120/radio/#

Umsetzung/Probleme

Für unsere Entwicklung haben wir uns einen vServer gemietet, auf dem die aktuelle Version vorliegt. Leider muss man sagen das unsere Anwendung diesen sehr schnell in die Knie zwingt und keiner Dauerbelastung stand hält. Das liegt daran das wir gerade einmal 512MB Flex-Ram zu Verfügung haben und alleine der FDS-Tomcat uns davon beim Starten ~350MB ‚klaut'(JVM). Wir mussten uns eigentlich auch schon einem ‚Trick‘ (siehe Conclusion) bedienen um den Tomcat überhaupt starten zu können. Das heißt um unsere Applikation eigentlich vernünftig zu hosten wäre ein vServer/RootServer mit mindestens 1GB Ram erforderlich. Leider haben wir nicht das benötigte Kleingeld dafür! Bitte habt somit Verständniss dafür, dass die Applikation keiner Dauerbelastung standhält und es durchaus sein kann das der Server irgendwann nicht mehr antwortet 🙁

Weitere Probleme ergaben sich mit dem Auslesen der Streaminformation bzw. dem generellen Abspielen, der Arbeit mit Flex insbesonderen mit einem strukturierten Aufbau mit mehreren mxml’s, AS3 Klassen und Events. Ein größeres Problem ergab sich zunächst auch mit der Arbeit um Hibernate bei dem viel Zeit verloren gegangen ist. Schuld war hier ran das wir nicht auf dem Server direkt unsere Klassen kompilierten und es folglich immer zu unschönen ‚Can’t find destination‘ Fehlern kam. Die Lösung bemerkten wir erst als wir uns wieder dem Datenaustausch zwischen Frontend und Backend via RPC’s zuwanden, wo wir zunächst vor dem selben Problem standen. Eine genauere Beschreibung des Problemes und ein kleines HowTo zu der Arbeit mit Flex und Hibernate auf dem FDS-Tomcat werde ich in nächster Zeit bloggen.

In diesem Projekt haben wir Papervision 2.0 für die Slideshow und die BassBox verwendet. Die komplette GUI wurde mit Flex selbst gestaltet. Für die Datenhaltung haben wir MySQL und JDBC verwendet. Eigentlich wollten wir das komplette Datenmanagement mit Hibernate und dem Flex LiveCycle umsetzten. Bedingt durch die anfänglichen Probleme in der Richtung, haben wir aber angefangen ein Teil davon über Servlets zu lösen. Mittlerweile sind aber auch Elemente wie zum Beispiel die Kommentar- und Bewertungsfunktion über Hibernate und RPC umgesetzt.

Wir sind sehr froh dieses Projekt sogar relativ zeitig vor dem Zeitablauf beendet zu haben und konnten ausserdem wieder eine Menge dazugelernen. Insbesondere ich konnte, dadurch das ich mich um das Backend und den Webserver gekümmert hatte, wieder viel in einer Disziplin dazulernen in der ich nicht so erfahren bin!

Da es sich um Studienprojekt handelt möchte ich euch noch das Pflichtenheft zur Verfügung stellen. Es wurde nach den Richtlinien von Heide Balzert erstellt und enthält auch eine OO-Analyse des Projektes. Dies soll lediglich als Anregung dienen und es gibt logischerweise kein Anspruch auf Richtigkeit/Vollständigkeit!

Pflichtenheft + OO-Analyse (.pdf, 373KB)

Techniken:

  • Flex/AS3
  • FDS-Tomcat (Webserver)
  • MySQL über JDBC
  • Papervision 3D 2.0
  • RPC Dienst des Adobe Live Cycle Data Services (LCDS)
    • HTTP Service (Servlets)
    • RemoteObjects (Hibernate)
  • persitente Datenhaltung via Hibernate (Java)
  • Verwendung des MVC-Modell 2 Frameworks
]]>
http://www.florian-oeser.de/2008/06/06/projekt-radiosity/feed/ 6
Flash CS3 / fscommand / UNC Paths http://www.florian-oeser.de/2008/06/06/flash-cs3-fscommand-unc-paths/ http://www.florian-oeser.de/2008/06/06/flash-cs3-fscommand-unc-paths/#respond Thu, 05 Jun 2008 23:33:31 +0000 http://www.florian-oeser.de/?p=27 Bei der Entwicklung an Projekt RingRong kam es zu einem spezifischem Problem beim Laden einer externen Anwendung(*.exe/*.bat). Ich blogge das in der Hoffung das mehr Leute, die das selbe Problem haben, schneller die Lösung finden, da die Problemlösung zumindest damals sehr schwer zu finden war.

Seit Flash CS3 ist es nicht mehr Möglich unter Win2k/XP/Vista *.exe Dateien zu starten. Grund dafür ist das intern nicht mehr mit DOS-Pfaden, sondern mit UNC-Pfaden gearbeitet wird.
Ich brauche auch gar nicht mehr dazu sagen, da alles in folgenden Link beschrieben ist. Und die passende Lösung dazu gibt es hier!

Viel Erfolg!

]]>
http://www.florian-oeser.de/2008/06/06/flash-cs3-fscommand-unc-paths/feed/ 0
Projekt: RingRong http://www.florian-oeser.de/2008/06/05/projekt-ringrong/ http://www.florian-oeser.de/2008/06/05/projekt-ringrong/#comments Thu, 05 Jun 2008 21:52:01 +0000 http://www.florian-oeser.de/?p=17 Einleitung

Das Projekt RingRong war für uns das erste große Projekt während des Studiums. Konzipiert und entwickelt wurde es während des 3. Semesters im Fach Multimedia Engineering I. Das Team bestand aus zwei Programmieren(Michael Palmer und ich), einem Grafiker(Martin Schmidt) und einem Modeller(Thomas Vogel), welcher ebenfalls für das zauberhafte Intro zuständig war. Insgesamt hatten wir rund vier Monate Zeit eine Multimediaanwendung zu entwickeln. Wir haben die Zeit komplett ausgereizt und haben eine sehr schönes Projekt abgeliefert, was jedem von uns viel abverlangt hat. Es ist komplett mit Flash CS3/AS3 und Papervision3D 1.5 realisiert.

Zunächst erst einmal ein paar Bilder und der Download damit das hier nicht alles so trocken wird 😀

ringrong_1

ringrong_tutorial

Die Anwendung

Das Projekt hat einen rein fiktiven Inhalt. Es dient der Vermarktung von Robotern, die so natürlich nicht existieren. Hauptteil ist der Baukasten, indem man sich nach Lust und Laune einen eigenen Roboter zusammen bauen kann. Weiterhin kann man den Roboter mit Upgrades ausstatten wie beispielsweise dem SecuritySystem. Aber schaut lieber selbst und entdeckt alle Features im Alleingang. Ihr werdet es nicht bereuen. Selbst ich schau es mir hin und wieder noch an und werd schon beim Intro schwach 😀

Umsetzung/Probleme

Meine konkrete Aufgabe war die Erstellung der ‚Tutorialapplikation‘ und einige Nebenläufigkeiten wie die Bildergalerien.

Es gab viele mehr oder minder große Probleme. Das größte war sicherlich unser massives Speicherproblem und die Performance. Ersteres konnte zum Glück gelöst werden. Die Perfomanceprobleme haben einfache Ursachen. Zum einen wird AS3 interpretiert und nicht kompiliert. Ausserdem greift Flash auch nicht auf die Grafikkarte zum Rendern zurück(in Flash10 soll dies jetzt möglich werden :-)). Desweiteren steckte pv3D noch fast in den Kinderschuhen mit der Version 1.5. Nunmehr ist pv3D v2.0 errschienen was durch verbesserte Renderarchitektur und Sachen wie Frustrum Culling auch einiges an Performance wieder gutmacht. Leider was es zu spät noch auf diese Version umzusteigen. Man brauchte also schon ein DualCore um bei der Tutorialapplikation auf rund 20 FPS zu kommen 😀

Trotzdem sind wir alle sehr froh dieses Projekt so gut umgesetzt zu haben. Wir haben viele Nächte zum Tag gemacht aber es hat sich gelohnt. Mal vom Lerneffekt und der Erfahrung mal ganz abgesehn 😀

Weitere Informationen und den Download findet ihr im Blog von Michael Palmer!

Techniken:

  • Flash CS3 mit AS3
  • Papervision3D 1.5
  • Maya
  • AfterEffects
  • Photoshop 😉
]]>
http://www.florian-oeser.de/2008/06/05/projekt-ringrong/feed/ 1
Papervision3D Workshop/Referat http://www.florian-oeser.de/2008/06/05/papervision3d-workshopreferat/ http://www.florian-oeser.de/2008/06/05/papervision3d-workshopreferat/#comments Thu, 05 Jun 2008 15:23:09 +0000 http://www.florian-oeser.de/?p=10 Im Rahmen unseres Projektes radioSiTY haben wir ein Referat mit anschließendem Workshop halten müssen. Das Thema war Papervision3D 2.0 und sollte einen groben Überblick über die Möglichkeiten von pv3D 2.0 und die Unterschiede/Vorteile zu pv3D 1.5 eröttern. Der Workshop gab den Teilnehmern die Chance ein kleines Basiswissen im Umgang mit pv3D zu erlernen. Es wurde gezeigt wie man pv3D in Flash und auch in Flex einbindet und damit arbeitet. Hervorheben möchte ich hier noch einmal die Canvas von meinem Mitentwickler Michael Palmer die zum Arbeiten mit Flex und pv3D benötigt wird.

Das Referat und den Workshop an sich möchte ich nun hier zur freien Nutzung veröffentlichen. Macht das beste draus ;-)

handout_workshop (.pdf, 63KB)

pv3d_2.0_referat (.pdf, 226KB)

flashpv3d_dateien (.zip, 3,7MB)

flexpv3d_dateien (.zip, 858KB)

Keine Garantie auf Richtigkeit/Vollständigkeit!

]]>
http://www.florian-oeser.de/2008/06/05/papervision3d-workshopreferat/feed/ 1