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/rest-api/class-wp-rest-server.php on line 1723 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/rest-api/class-wp-rest-server.php on line 1723 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/rest-api/class-wp-rest-server.php on line 1723 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/rest-api/class-wp-rest-server.php on line 1723 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/rest-api/class-wp-rest-server.php on line 1723 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/rest-api/class-wp-rest-server.php on line 1723 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/rest-api/class-wp-rest-server.php on line 1723 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/rest-api/class-wp-rest-server.php on line 1723 {"id":51,"date":"2008-07-08T14:14:19","date_gmt":"2008-07-08T12:14:19","guid":{"rendered":"http:\/\/www.florian-oeser.de\/?p=51"},"modified":"2008-07-08T14:15:54","modified_gmt":"2008-07-08T12:15:54","slug":"howto-fds-tomcat-datamanagement-hibernate","status":"publish","type":"post","link":"http:\/\/www.florian-oeser.de\/2008\/07\/08\/howto-fds-tomcat-datamanagement-hibernate\/","title":{"rendered":"HowTo: FDS-Tomcat + Datamanagement + Hibernate"},"content":{"rendered":"

Einleitung<\/h4>\n

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.<\/p>\n

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 \u00fcber das entspechende Result-Event gel\u00f6st werden. Jetzt werden \u00c4nderungen an den Daten zwischem dem Server und (wahlweise) allen Clients instant aktualisiert. Das hei\u00dft wenn ein Client Daten \u00e4ndert wird automatisch das Backend informiert, welches sich sofort um die persistente Speicherung durch Hibernate k\u00fcmmert und alle anderen Clients \u00fcber die entsprechenden \u00c4nderungen informiert(push).<\/p>\n

Wir verwenden dazu nur noch den FDS-Tomcat da dieser Service nicht im BlazeDS integriert ist. Sicherlich w\u00fcrde sich das nachr\u00fcsten lassen, jedoch habe ich mich damit nicht besch\u00e4ftigt. 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.<\/p>\n

Im \u00dcbrigen benutzen wir auch nicht den Hibernate Assembler\/Adapter sondern bleiben bei der direkten Hibernate-Implementierung. Falls ihr euch f\u00fcr diesen Assembler interessiert gibt es bei den Testdrive-Tutorials ebenfalls ein Beispiel. Das ist sehr \u00e4hnlich dem Sample 8 benutzt dann aber Hibernate.<\/p>\n

Um die Umsetzung nachvollziehen zu k\u00f6nnen, m\u00f6chte ich euch wieder gleich den Source geben. Darin erhalten ist dann ebenfalls gleich wieder ein SQL-Dump.<\/p>\n

Die Umsetzung<\/h4>\n

Das Backend<\/h5>\n

F\u00fcr die Umsetzung bedienen wir uns wieder der Stream-Tabelle aus dem Servlets-HowTo.<\/p>\n

Nun werden wir \u00e4hnlich wie im Sample 8 die Tabelle auslesen und in ein DataGrid schreiben. Es wird nicht viel Arbeit, da wir nur eine neue Klasse einf\u00fchren werden und ansonsten nur vorhandene Sachen erweitern.<\/p>\n

Anfangen m\u00f6chte ich mit dem sogenannten Streamassembler. Dieser implemtiert den AbstractAssembler aus dem LCDS. Das hei\u00dft wir m\u00fcssen die Methoden fill(), getItem(), update() und deleteItem() \u00fcberschreiben. Der Assembler ist sehr wichtig, da seine Methoden aufgerufen werden wenn es zu \u00c4nderungen am Tabelleninhalt\u00a0kommt. Das hei\u00dft unsere Client arbeitet nicht mehr direkt mit dem HibernateAssembler. Das macht jetzt der Streamassembler direkt in den \u00fcberschriebenen Funktionen. Da zum Aktualisieren der Daten aber erstmal nur fill() und update() wichtig ist, beschr\u00e4nke ich mich auf deren Implementierung. Die anderen k\u00f6nnt ihr sicher alleine implementieren \ud83d\ude42<\/p>\n

\r\npackage flex.radioSiTY;\r\n\r\nimport java.util.List;\r\nimport java.util.Collection;\r\nimport java.util.Map;\r\n\r\nimport flex.data.DataSyncException;\r\nimport flex.data.assemblers.AbstractAssembler;\r\n\r\npublic class StreamAssembler extends AbstractAssembler {\r\n\r\n\tpublic Collection fill(List fillArgs) {\r\n\t\tHibernateHandler service = new HibernateHandler();\r\n\t\treturn service.getStreams();\r\n\t}\r\n\r\n\t\/*public Object getItem(Map identity) {\r\n\t\t\r\n\t\t}\r\n\t}*\/\r\n\r\n\tpublic void createItem(Object item) {\r\n\t\t\r\n\t}\r\n\r\n\tpublic void updateItem(Object newVersion, Object prevVersion, List changes) {\r\n\t\tHibernateHandler service = new HibernateHandler();\r\n\t\tservice.update((Stream) newVersion);\t\t\r\n\t}\r\n\r\n\tpublic void deleteItem(Object item) {\r\n\t\t\r\n\t}\r\n\t\r\n}\r\n\r\n<\/pre>\n

Nun kommen die \u00c4nderungen an unserem bekannten HibernateHandler. Diesem f\u00fcgen wir die zwei neuen Funktionen, die der StreamAssembler ben\u00f6tigt, hinzu:<\/p>\n

\r\npublic List getStreams() throws DAOException {\r\n\r\n\t\tList list = new ArrayList();\r\n\t\tSession sess = null;\r\n\t\tTransaction trx = null;\r\n\r\n\t\ttry {\r\n\t\t\tsess = sessionFactory.openSession();\r\n\t\t\ttrx = sess.beginTransaction();\r\n\t\t\tSystem.out.println("\\nStreams:");\r\n\t\t\tList streams = sess.createQuery("from Stream").list();\r\n\t\t\tfor (int i = 0; i < streams.size(); i++) {\r\n\t\t\t\tStream stream = (Stream) streams.get(i);\r\n\t\t\t\tlist.add(new Stream(stream.getId(), stream\r\n\t\t\t\t\t\t.getUrl(), stream.getHomepage(), stream.getName(),\r\n\t\t\t\t\t\tstream.getgenreId(), stream.getImage()));\r\n\t\t\t}\r\n\t\t\t\ttrx.commit();\r\n\t\t\t} catch (HibernateException ex) {\r\n\t\t\t\tif (trx != null)\r\n\t\t\t\t\ttry {\r\n\t\t\t\t\t\ttrx.rollback();\r\n\t\t\t\t\t} catch (HibernateException exRb) {\r\n\t\t\t\t\t}\r\n\t\t\t\tthrow new RuntimeException(ex.getMessage());\r\n\t\t\t} finally {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tif (sess != null)\r\n\t\t\t\t\t\tsess.close();\r\n\t\t\t\t} catch (Exception exCl) {\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\treturn list;\r\n\r\n\t}\r\n\t\r\n\tpublic void update(Stream stream) throws DAOException {\r\n\r\n\t\tSession sess = null;\r\n\t\tTransaction trx = null;\r\n\t\t\r\n\t\ttry {\r\n\t\t\tsess = sessionFactory.openSession();\r\n\t\t\ttrx = sess.beginTransaction();\r\n\t\t\t\r\n\t\t\tsess.update(stream);\r\n\t\t\ttrx.commit();\r\n\t\t} catch (HibernateException ex) {\r\n\t\t\tif (trx != null)\r\n\t\t\t\ttry {\r\n\t\t\t\t\ttrx.rollback();\r\n\t\t\t\t} catch (HibernateException exRb) {\r\n\t\t\t\t\tSystem.out.println(exRb.toString());\r\n\t\t\t\t}\r\n\t\t\tthrow new RuntimeException(ex.getMessage());\r\n\t\t} finally {\r\n\t\t\ttry {\r\n\t\t\t\tif (sess != null)\r\n\t\t\t\t\tsess.close();\r\n\t\t\t} catch (Exception exCl) {\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n&#91;\/sourcecode&#93;\r\n\r\nDamit das ganze funktionieren kann brauchen wir in der Streamklasse noch zwei Konstruktoren:\r\n\r\n&#91;sourcecode language='java'&#93;\r\npackage flex.radioSiTY;\r\n\r\nimport java.util.*;\r\n\r\npublic class Stream \r\n{\r\n  private int    id;\r\n  private String url;\r\n  private String homepage;\r\n  private String name;\r\n  private int genreId;\r\n  private String image;\r\n  private Set    user     = new HashSet();\r\n  private Set    comments = new HashSet();\r\n  \r\n  public Stream() {name = "test"; }\r\n  \r\n  public Stream(int id, String url, String homepage, String name, int genreId, String image) {\r\n\t\tthis.id = id;\r\n\t\tthis.url = url;\r\n\t\tthis.homepage = homepage;\r\n\t\tthis.image = image;\r\n\t\tthis.name = name;\r\n\t\tthis.genreId = genreId;\t\t\r\n\t}\r\n  \r\n  public Stream(Stream stream) {\r\n\t\tthis.id = stream.getId();\r\n\t\tthis.url = stream.getUrl();\r\n\t\tthis.homepage = stream.getHomepage();\r\n\t\tthis.image = stream.getImage();\r\n\t\tthis.name = stream.getName();\r\n\t\tthis.genreId = stream.getgenreId();\t\r\n\t}\r\n\r\n  public int    getId()         { return id; }\r\n  public String getUrl()    { return url; }\r\n  public String getHomepage()    { return homepage; }\r\n  public String getName()      { return name; }\r\n  public int getgenreId()    { return genreId; }\r\n  public String getImage()      { return image; }\r\n  public Set    getUser()     { return user; }\r\n  public Set    getComments() { return comments; }\r\n\r\n  public void setId(         int id         ) { this.id = id; }\r\n  public void setUrl( String url    ) { this.url = url; }\r\n  public void setHomepage( String homepage    ) { this.homepage = homepage; }\r\n  public void setName( String name    ) { this.name = name; }\r\n  public void setgenreId ( int genre    ) { this.genreId = genre; }\r\n  public void setImage(   String image      ) { this.image = image; }\r\n  public void setUser(     Set user     ) { this.user = user; }\r\n  public void setComments( Set comments ) { this.comments = comments; }\r\n}\r\n&#91;\/sourcecode&#93;\r\n\r\nDas waren jetzt auch schon alle \u00c4nderungen die das Backend betreffen. \r\n\r\n<h5>Das Frontend<\/h5>\r\n\r\nF\u00fcr das Frontend erstellen wir einfach ein Datagrid, welches nun durch den StreamAssembler \u00fcber die Methode fill() gef\u00fcllt 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:\r\n\r\n\r\n<?xml version="1.0" encoding="utf-8"?>\r\n<mx:Application xmlns:mx="http:\/\/www.adobe.com\/2006\/mxml" xmlns="*" backgroundColor="#FFFFFF" viewSourceURL="srcview\/index.html">\r\n\t\r\n\t<mx:ArrayCollection id="streams"\/> \r\n\t<mx:DataService id="ds" destination="stream"\/>\r\n\t<Stream\/>\r\n\t\r\n\t<mx:DataGrid dataProvider="{streams}" editable="true" width="100%" height="100%">\r\n\t\t<mx:columns>\r\n\t\t\t<mx:DataGridColumn dataField="url" headerText="Url"\/>\r\n\t\t\t<mx:DataGridColumn dataField="homepage" headerText="Homepage"\/>\r\n\t\t\t<mx:DataGridColumn dataField="name" headerText="Name"\/>\r\n\t\t\t<mx:DataGridColumn dataField="genreId" headerText="Genre"\/>\r\n\t\t\t<mx:DataGridColumn dataField="image" headerText="Image"\/>\r\n\t\t<\/mx:columns>\r\n\t<\/mx:DataGrid>\r\n\t\r\n\t<mx:Button label="Get Data" click="ds.fill(streams)"\/> \r\n\t\r\n<\/mx:Application>\r\n<\/pre>\n

Die Methode updateItem() des StreamAssemblers muss nicht aufgerufen werden, da diese bei \u00c4nderungen an der Tabelle automatisch aufgerufen wird \ud83d\ude42<\/p>\n

Damit das ganze \u00fcberhaupt funktionieren kann m\u00fcssen wir nat\u00fcrlich noch die Destination f\u00fcr den DataService anlegen. Das passiert \u00e4hnlich wie bei den RemoteObjects. Nur benutzen wir jetzt nicht mehr die remoting-config.xml sondern die datamanagement-config.xml!Einfach folgenden Eintrag hinzuf\u00fcgen:<\/p>\n

\r\n<destination id="stream">\r\n\r\n        <adapter ref="java-dao" \/>\r\n\r\n        <properties>\r\n            <source>flex.radioSiTY.StreamAssembler<\/source>\r\n            <scope>application<\/scope>\r\n\r\n            <metadata>\r\n                <identity property="id"\/>\r\n            <\/metadata>\r\n\r\n            <network>\r\n                <session-timeout>20<\/session-timeout>\r\n                <paging enabled="false" pageSize="10" \/>\r\n                <throttle-inbound policy="ERROR" max-frequency="500"\/>\r\n                <throttle-outbound policy="REPLACE" max-frequency="500"\/>\r\n            <\/network>\r\n        <\/properties>\r\n    <\/destination>\r\n<\/pre>\n

Conclusion<\/h4>\n

So das wars dann auch schon. \u00d6ffnet die Tabelle einfach mal in zwei Tab’s und \u00e4ndert in der einen etwas. Siehe da die andere Tabelle wird instant aktualisiert \ud83d\ude42<\/p>\n

Leider habe ich mich nicht mit den verschiedenen Einstellungsm\u00f6glichkeiten was das Datamanagement betrifft auseinandersetzten k\u00f6nnen. Da gibt es einige Sachen die sich konfigurieren lassen. Zum Beispiel auf welchen Clients \u00fcberhaupt aktualisiert werden soll etc. Dazu findet ihr aber in dem FDMS-Tutorial wenn ich micht recht entsinne einiges.<\/p>\n

So das wars f\u00fcr diese How-To Reihe. Ich hoffe bei euch hat alles geklappt und hattet damit genausoviel Spass wie ich \ud83d\ude42<\/p>\n

Bei Fragen und Anregungen k\u00f6nnt ihr mir wie immer mailen oder ein Kommentar hinterlassen!<\/p>\n","protected":false},"excerpt":{"rendered":"

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 […]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[9,6],"tags":[],"_links":{"self":[{"href":"http:\/\/www.florian-oeser.de\/wp-json\/wp\/v2\/posts\/51"}],"collection":[{"href":"http:\/\/www.florian-oeser.de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.florian-oeser.de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.florian-oeser.de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.florian-oeser.de\/wp-json\/wp\/v2\/comments?post=51"}],"version-history":[{"count":0,"href":"http:\/\/www.florian-oeser.de\/wp-json\/wp\/v2\/posts\/51\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.florian-oeser.de\/wp-json\/wp\/v2\/media?parent=51"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.florian-oeser.de\/wp-json\/wp\/v2\/categories?post=51"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.florian-oeser.de\/wp-json\/wp\/v2\/tags?post=51"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}