<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Christoph Bünte &nbsp;&raquo; Software Entwicklung Berlin</title>
	<atom:link href="http://www.christophbuente.de/tag/anleitung/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.christophbuente.de</link>
	<description>Software Entwicklung</description>
	<lastBuildDate>Tue, 07 Dec 2010 11:30:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>Stripes Framework &#8211; Tests für ActionBeans im Wizard Modus</title>
		<link>http://www.christophbuente.de/2008-01-24-stripes-framework-tests-fur-actionbeans-im-wizard-modus/</link>
		<comments>http://www.christophbuente.de/2008-01-24-stripes-framework-tests-fur-actionbeans-im-wizard-modus/#comments</comments>
		<pubDate>Thu, 24 Jan 2008 22:44:17 +0000</pubDate>
		<dc:creator>Christoph Bünte</dc:creator>
				<category><![CDATA[Java JEE]]></category>
		<category><![CDATA[Web Entwicklung]]></category>
		<category><![CDATA[actionBean]]></category>
		<category><![CDATA[anleitung]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JEE]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[mock]]></category>
		<category><![CDATA[MockRoundTrip]]></category>
		<category><![CDATA[MockServletContext]]></category>
		<category><![CDATA[stripes]]></category>
		<category><![CDATA[stripes framework]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[tests]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[unit tests]]></category>
		<category><![CDATA[wizard mode]]></category>
		<category><![CDATA[wizard modus]]></category>
		<category><![CDATA[__fp]]></category>

		<guid isPermaLink="false">http://www.christophbuente.de/2008-01-24-stripes-framework-tests-fur-actionbeans-im-wizard-modus/</guid>
		<description><![CDATA[Bei meinem aktuellen Kunden wurde das Stripes Framework verwendet, um eine Java basierte Webanwendung zu erstellen. Für mehrseitige Formulare bietet Stripes ActionBeans mit einen Wizard Modus an. Dieser zeichnet sich dadurch aus, dass alle bereits ausgefüllten Formularfelder als versteckte Felder in alle folgenden Formulare eingefügt werden. Dieser Modus erspart bei mehrseitigen Formularen viel Arbeit, aber [...]]]></description>
			<content:encoded><![CDATA[<p>Bei meinem aktuellen Kunden wurde das <a href="http://www.stripesframework.org/">Stripes Framework</a> verwendet, um eine Java basierte Webanwendung zu erstellen. Für mehrseitige Formulare bietet Stripes ActionBeans mit einen <a href="http://www.stripesframework.org/display/stripes/Wizard+Forms">Wizard Modus</a> an. Dieser zeichnet sich dadurch aus, dass alle bereits ausgefüllten Formularfelder als versteckte Felder in alle folgenden Formulare eingefügt werden. Dieser Modus erspart bei mehrseitigen Formularen viel Arbeit, aber wie lässt sich dieser Wizard Modus am besten Testen? In diesem Artikel wird beschrieben, wie man mit Hilfe dem Stripes eigenen MockServletContexts sinnvolle Unit tests schreiben kann.</p>
<p><span id="more-31"></span></p>
<p>Die Dokumentation für <a href="http://www.stripesframework.org/display/stripes/Unit+Testing#UnitTesting-Approach2%3AMockContainerUsage">Stripes Unit tests</a> beschreibt sehr ausführlich, wie man mit Hilfe des MockServletContext eine Testinfrastruktur aufbaut, die es ermöglicht die ActionBeans ausserhalb des <acronym title="Java Enterprise Edition" lang="en">JEE</acronym>-Containers zu testen. Dies funktioniert für klassische ActionBeans ganz wunderbar. Doch beim schreiben von Tests für ActionBeans im Wizard Mode fiel auf, dass die Simulation eines Submits nicht funktionierte. Im Wizard Modus erzeugt das <a href="http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/tag/FormTag.html">Stripes FormTag</a> ein zusätzliches verstecktes Formularfeld mit dem Namen &#8220;__fp&#8221;, welches alle Feldnamen des aktuellen Formulars in verschlüsselter Form enthält. Ohne dieses Feld verweigert der Stripes Dispatcher die Arbeit! Nimmt man nun einen beliebigen Wert und legt ihn in diesem Feld ab, so erzeugt das ebenfalls einen Fehler:<small>(Der Rechtschreibfehler ist tatsächlich aus dem Framework.)</small></p>
<p><code>Stripes attmpted and failed to decrypt the non-null value in the 'fields present' field.</code></p>
<p>Auch ist es nicht sinnvoll, einen beliebigen Text mit Hilfe des <code>CryptoUtil</code> zu verschlüsseln. Der Submit kann dann zwar erfolgreich simuliert werden, jedoch werden sämtliche Validierungsregel ignoriert. Mit folgenden Zeilen Code, kann ein korrekter Wert für das &#8220;__fp&#8221; Feld erzeugt werden:</p>
<pre lang="java">// Alle Feldnamen des aktuellen Formulars in eine Liste aufnehmen
   List fields = new ArrayList();
   fields.add("username");
   fields.add("password");
// Alle Feldnamen mit Trennzeichen zusammenfassen
   String hiddenFieldValue = HtmlUtil.combineValues(fields);
// servlet engine configurieren
   MockServletContext ctx = TestFixture.getServletContext();
   MockRoundtrip trip = new MockRoundtrip(this.ctx, YourCustomActionBean.class);
   HttpServletRequest request = (HttpServletRequest) trip.getRequest();
   hiddenFieldValue = CryptoUtil.encrypt(hiddenFieldValue, request);
   trip.setParameter(StripesConstants.URL_KEY_FIELDS_PRESENT, hiddenFieldValue);</pre>
<p>Für das Testen der Feldvalidierung ist es wichtig, dass die Feldnamen mit dem Wert des <code>&lt;input name="" /&gt;</code> Name Attributes in dem jeweiligen Formular übereinstimmen. Denn es werden tatsächlich nur die Felder validiert, die aus dem decodiertem Inhalt des &#8220;__fp&#8221; Feldes ausgelesen werden können.</p>
<p>Angenommen der oben abgebildete Code wird in der <code>setup()</code> Methode eines Unit Tests ausgeführt und speichert das <code>MockRoundtrip</code> Object in einem privaten Member, könnte ein Beispieltest könnte dann so aussehen:</p>
<pre lang="java">@Test
public void testLogin() throws Exception {
	trip.setParameter("username", "christophbuente");
	trip.setParameter("password", "secret");
	trip.execute("login");
	YourCustomActionBean bean = trip.getActionBean(YourCustomActionBean.class);
	Assert.assertTrue("Destination", "/account", trip.getDestination());
}</pre>
<p>Ich hoffe, dass diese Informationen ausreichen, um sinnvolle Unit Tests für ActionBeans im Wizard Modus zu schreiben. Bei Fragen helfe ich gerne weiter. Und wie immer sind Kommentare sehr willkommen.</p>
<div id="crp_related"><h3>Ähnliche Beiträge:</h3><ul><li><a href="http://www.christophbuente.de/2007-10-23-bots-aussperren-mit-captcha/" rel="bookmark" class="crp_title">captcha tutorial &#8211; Bots aussperren</a></li><li><a href="http://www.christophbuente.de/2007-11-17-canoo-webtest-web-anwendungen-automatisch-testen/" rel="bookmark" class="crp_title">canoo webtest &#8211; Web-Anwendungen automatisch testen</a></li><li><a href="http://www.christophbuente.de/2009-05-16-remarkable-rails-anwendungen-automatisch-testen/" rel="bookmark" class="crp_title">Remarkable &#8211; Rails Anwendungen automatisch testen</a></li><li><a href="http://www.christophbuente.de/2007-11-24-advancing-rails-ein-workshop-mit-david-a-black/" rel="bookmark" class="crp_title">Advancing Rails &#8211; Ein Workshop mit David A. Black</a></li><li><a href="http://www.christophbuente.de/2007-08-05-objekte-und-beziehungen/" rel="bookmark" class="crp_title">Objekte und Beziehungen</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.christophbuente.de/2008-01-24-stripes-framework-tests-fur-actionbeans-im-wizard-modus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VoiceGlue Konfiguration &#8211; Server für Sprachanwendungen einrichten</title>
		<link>http://www.christophbuente.de/2007-12-21-voiceglue-konfiguration-server-fur-sprachanwendungen-einrichten/</link>
		<comments>http://www.christophbuente.de/2007-12-21-voiceglue-konfiguration-server-fur-sprachanwendungen-einrichten/#comments</comments>
		<pubDate>Fri, 21 Dec 2007 19:25:58 +0000</pubDate>
		<dc:creator>Christoph Bünte</dc:creator>
				<category><![CDATA[Unix shell]]></category>
		<category><![CDATA[Voice]]></category>
		<category><![CDATA[agi]]></category>
		<category><![CDATA[anleitung]]></category>
		<category><![CDATA[asr]]></category>
		<category><![CDATA[asterisk]]></category>
		<category><![CDATA[dtmf]]></category>
		<category><![CDATA[hilfe]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[sip]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[speech]]></category>
		<category><![CDATA[tts]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[voiceglue]]></category>
		<category><![CDATA[voicexml]]></category>
		<category><![CDATA[vox]]></category>
		<category><![CDATA[vxglue]]></category>
		<category><![CDATA[vxml]]></category>

		<guid isPermaLink="false">http://www.christophbuente.de/2007-12-21-voiceglue-konfiguration-server-fur-sprachanwendungen-einrichten/</guid>
		<description><![CDATA[[lang_de]In meinem letzten Artikel habe ich die Installation der IVR Software VoiceGlue unter Fedora Core 8 in einer Parallels Desktop VM beschrieben. Nun möchte ich eine Anleitung für die Einrichtung von VoiceGlue nachliefern. Damit wird es jedem möglich, eine VoiceXML basierte Sprachanwendung aufzusetzen. [ad#vert-banner] Nachdem alle Schritte aus der Installationsanleitung befolgt wurden, sind folgende Komponenten [...]]]></description>
			<content:encoded><![CDATA[<p>[lang_de]In meinem <a title="VoiceGlue Installation - Interactive Voice Response leicht gemacht" href="http://www.christophbuente.de/2007-12-06-voiceglue-installation-interactive-voice-response-leicht-gemacht/">letzten Artikel</a> habe ich die Installation der <acronym title="Interactive Voice Response" lang="en">IVR</acronym> Software <a title="VoiceGlue" href="http://www.voiceglue.org">VoiceGlue</a> unter <a href="http://fedoraproject.org/">Fedora Core 8</a> in einer <a href="http://www.parallels.com/en/products/desktop/">Parallels Desktop VM</a> beschrieben. Nun möchte ich eine Anleitung für die Einrichtung von VoiceGlue nachliefern. Damit wird es jedem möglich, eine VoiceXML basierte Sprachanwendung aufzusetzen.<br />
<span id="more-27"></span></p>
<p>[ad#vert-banner]</p>
<p>Nachdem alle Schritte aus der Installationsanleitung befolgt wurden, sind folgende Komponenten auf dem System installiert:</p>
<ul>
<li><a href="http://www.perl.org/">perl</a> (Skriptsprache)</li>
<li><a href="http://www.asterisk.org/">asterisk</a> (Telefonieserver)</li>
<li><a href="http://www.openvxi.org/">openVXI</a> (Open Source VoiceXML Interpreter)</li>
<li><a href="http://www.speech.cs.cmu.edu/flite/index.html">flite</a> (engl. <acronym title="Text To Speech" lang="en">TTS</acronym> Engine)</li>
<li><a href="http://www.voiceglue.org">voiceglue</a> (IVR Software)</li>
</ul>
<p>Um tatsächlich Anrufe über das Telefon- oder auch VoIP Netz entgegen nehmen zu können, muss der asterisk Server konfiguriert werden. Eine vollständige Beschreibung der asterisk Konfiguration würde allerdings den Rahmen dieses Tutorials sprengen. Aus diesem Grund wird lediglich die Konfiguration erklärt, mit er es möglich ist, mit Hilfe eines sogenannten <a title="Softphone" href="http://de.wikipedia.org/wiki/Softphone">Softphones</a> an der Sprachanwendung anzurufen. Für vielschichtige asterisk Konfigurationen findet man in <a title="Asterisk" href="http://www.amazon.de/gp/redirect.html%3FASIN=0596009623%26tag=chribuensofte-21%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0596009623%253FSubscriptionId=1YNZ339ZCHHAKYFSY702">Asterisk: The Future if Telephony</a> ausreichend Hilfe.</p>
<p>Als erstes benötigen wir für die Annahme von Anrufen via <acronym title="Session Initiation Protocol" lang="en">SIP</acronym> einen eigenen Kontext in der Datei: <code>/etc/asterisk/manager.conf</code>. Die folgenden Zeilen sollte man am besten am Ende der Datei einfügen:</p>
<pre lang="conf">[phoneglue]
secret=phoneglue
read = system,call,log,verbose,command,agent,user
write = system,call,log,verbose,command,agent,user</pre>
<p>Ausserdem muss der Manager noch aktiviert werden. Deswegen sollte man sicherstellen, dass in der gleichen Datei die Variable <code>enabled=yes</code> gesetzt ist.</p>
<p>Danach wird asterisk so konfiguriert, dass alle angenommenen Anrufe per <acronym title="Asterisk Gateway Interface" lang="en">AGI</acronym> an den Voicebrowser weitergeleitet werden. Durch die Verwendung von AGI ist es möglich, den Voicebrowser auch auf einem anderen Server zu betreiben und die Verbindung via Netzwerk herzustellen. Dies nimmt bei vielen Anrufen die Last vom System. Die Konfiguration wird in der Datei <code>/etc/asterisk/extensions.conf</code> vorgenommen. Auch hier ist es wieder sinnvoll einen neuem Kontext am Ende der Datei einzufügen:</p>
<pre lang="conf">[phoneglue]
exten =&gt; 1,1,Agi(agi://localhost)
exten =&gt; 1,2,Hangup</pre>
<p>Die Einträge für die Extensions beginnen mit einer <em>1</em>. Dies ist die Durchwahl für die Sprachanwendung. Der Aufruf &#8220;Agi(agi://localhost) verbindet nun den Voicebrowser mit dem Anrufer.</p>
<p>Möchte man nun alle eingehenden Anrufe, welche mit SIP initiiert werden, an die Sprachanwendung leiten, ist noch eine Änderung in der Datei <code>/etc/asterisk/sip.conf</code> nötig. Der Standard Kontext muss von <code>default</code> auf <code>phoneglue</code> gesetzt werden.</p>
<pre lang="conf">[general]
context=phoneglue</pre>
<p>Damit ist die Konfiguration von asterisk schon abgeschlossen. Nun kann es mit der Konfiguration der Sprachanwendung weitergehen.</p>
<p>VoiceXML basierte Sprachanwendungen benötigen einen <acronym title="Hyper Text Transport Protocol" lang="en">HTTP</acronym> Server, welcher die statischen oder dynamisch erzeugten *.vxml Dateien ausliefert. Auch hier haben die Entwickler von VoiceGlue mitgedacht, indem das System so konfigurierbar ist, dass der VoiceXML Server auf einer separaten Maschine laufen kann. Zu Demonstrationszwecken genügt es hier allerdings, dass alle Dienste auf einer Maschine laufen. Die Konfiguration wird in der Datei <code>/etc/voiceglue.conf</code> vorgenommen. Hier genügt ein Eintrag, der auf die Einstiegsseite der Sprachanwendung zeigt.</p>
<pre lang="conf"> * http://localhost/index.vxml</pre>
<p>Diese Datei muss vom lokalen <a href="http://apache.org">Apache</a> ausgeliefert werden. Falls noch nicht geschehen, sollte der Apache jetzt gestartet werden:</p>
<pre lang="shell">sudo service httpd start</pre>
<p>Standardmässig liegen die <acronym title="Hyper Text Markup Language" lang="en">HTML</acronym> für den Apache unter Fedora im Verzeichnis <code>/var/www/html</code>. Genau an dieser Stelle legen wir eine klassische <span lang="en">Hello World</span> Anwendung in Form einer VoiceXML Datei mit folgendem Inhalt ab:</p>
<pre lang="xml">
<form>

      Hello World. This is my first voiceglue application.</form>
</pre>
<p>Damit ist die Konfiguration abgeschlossen. Alle Dienste sind vollständig konfiguriert und sollten jetzt gestartet werden.</p>
<pre lang="bash">sudo service asterisk start
sudo service phoneglue start
sudo service voiceglue start</pre>
<p>Als letztes wollen wir überprüfen, ob die Komfiguration erfolgreich war. Dazu benötigen wir ein Softphone. Eine freie Version findet man bei <a href="http://sjlabs.com">SJLabs</a>. Das Telefon ist für Windows, Linux und OS X verfügbar. Nach dem herunterladen muss im Menupunkt <em>Phone-&gt;Services</em> das SIP Protolkoll gewählt werden. Anschließend wählen wir unseren lokalen asterisk Dienst mit der Durchwahl <code>1@localhost</code> an.</p>
<p>Basierend auf der gezeigten Konfiguration lassen sich beliebige Sprachanwendungen erstellen. Wie jedoch schon im Beitrag <a title="VoiceGlue Installation - Interactive Voice Response leicht gemacht" href="http://www.christophbuente.de/2007-12-06-voiceglue-installation-interactive-voice-response-leicht-gemacht/">VoiceGlue Installation &#8211; Interactive Voice Response leicht gemacht</a> beschrieben, fehlt die Intergration einer <acronym title="Automatic Speech Recognition" lang="en">ASR</acronym> Engine. Somit beschränken sich Anrufereingaben auf <acronym title="Dual Tone Multiple Frequencies" lang="en">DTMF</acronym>.[/lang_de]</p>
<div id="crp_related"><h3>Ähnliche Beiträge:</h3><ul><li><a href="http://www.christophbuente.de/2007-12-06-voiceglue-installation-interactive-voice-response-leicht-gemacht/" rel="bookmark" class="crp_title">VoiceGlue Installation &#8211; Interactive Voice Response leicht gemacht</a></li><li><a href="http://www.christophbuente.de/2007-11-17-canoo-webtest-web-anwendungen-automatisch-testen/" rel="bookmark" class="crp_title">canoo webtest &#8211; Web-Anwendungen automatisch testen</a></li><li><a href="http://www.christophbuente.de/2007-11-25-ruby-on-rails-auf-mac-os-x-5-minuten-kurzanleitung/" rel="bookmark" class="crp_title">Ruby on Rails auf Mac OS X &#8211; 5 Minuten Kurzanleitung</a></li><li><a href="http://www.christophbuente.de/2009-09-09-500-internal-server-error-apache-config-vs-wp-super-cache/" rel="bookmark" class="crp_title">500 Internal Server Error &#8211; Apache config vs. WP-Super-Cache</a></li><li><a href="http://www.christophbuente.de/2007-10-05-frei-nehmen-um-zu-lernen/" rel="bookmark" class="crp_title">Rails tutorial &#8211;  Eine Woche lang Agile Webentwicklung</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.christophbuente.de/2007-12-21-voiceglue-konfiguration-server-fur-sprachanwendungen-einrichten/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby on Rails auf Mac OS X &#8211; 5 Minuten Kurzanleitung</title>
		<link>http://www.christophbuente.de/2007-11-25-ruby-on-rails-auf-mac-os-x-5-minuten-kurzanleitung/</link>
		<comments>http://www.christophbuente.de/2007-11-25-ruby-on-rails-auf-mac-os-x-5-minuten-kurzanleitung/#comments</comments>
		<pubDate>Sun, 25 Nov 2007 13:33:25 +0000</pubDate>
		<dc:creator>Christoph Bünte</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[anleitung]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[kurzanleitung]]></category>
		<category><![CDATA[locomotive]]></category>
		<category><![CDATA[mac os x]]></category>
		<category><![CDATA[mac user]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[Software Entwicklung]]></category>
		<category><![CDATA[tutorium]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[Web Entwicklung]]></category>

		<guid isPermaLink="false">http://www.christophbuente.de/2007-11-25-ruby-on-rails-auf-mac-os-x-5-minuten-kurzanleitung/</guid>
		<description><![CDATA[Ruby on Rails isst in aller Munde, wenn es um Webentwicklung geht. Ich werde in Zukunft eine Reihe von Artikeln veröffentlichen, die etwas tiefer in die Materie eindringen. Dazu ist es aber nötig, dass jeder Leser weiss, wie man Ruby on Rails auf seinem Rechner zum laufen bekommt und ein Projekt erzeugt. Aus diesem Grund [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://rubyonrails.com/" title="Webentwicklung, die nicht weh tut">Ruby on Rails</a> isst in aller Munde, wenn es um Webentwicklung geht. Ich werde in Zukunft eine Reihe von Artikeln veröffentlichen, die etwas tiefer in die Materie eindringen. Dazu ist es aber nötig, dass jeder Leser weiss, wie man Ruby on Rails auf seinem Rechner zum laufen bekommt und ein Projekt erzeugt. Aus diesem Grund hier eine 5 Minuten Kurzanleitung. Als Mac User werde speziell auf das Betriebsystem <a href="http://www.apple.com/de/macosx/">Mac OS X</a> eingehen.</p>
<p><span id="more-22"></span></p>
<p>Um mit Rails auf dem Mac zu beginnen, gibt es zwei Möglichkeiten:</p>
<ol>
<li> 		<a href="http://hivelogic.com/narrative/articles/ruby-rails-mongrel-mysql-osx">Kompilieren und installieren aller benötigten Komponenten</a></li>
<li> 		Benutzen einer Applikation, die schon alles mitbringt.</li>
</ol>
<p>Getreu dem Motto dieses Artikels, empfehle ich den schnellen, einfachen Weg <img src='http://www.christophbuente.de/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  <a href="http://locomotive.raaum.org/" title="Ryan Rauum">Ryan Rauum</a> stellt auf seiner Website eine Cocoa Anwendung zur Verfügung, die bereits alle Komponenten &#8211; bis auf die Datenbank &#8211; in einer Anwendung bündelt. Die Installation ist so einfach, wie bei jeder anderen Anwendung.</p>
<ul>
<li> 		<a href="http://locomotive.raaum.org" title="Locomotive herunterladen">Herunterladen</a></li>
<li> 		DMG Datei doppelt anklicken</li>
<li> 		Locomotive Symbol in das Programmverzeichnis ziehen</li>
</ul>
<p>Als Datenbank empfehle ich für die ersten Schritte <a href="http://www.mysql.com">MySQL</a>. Über den Produktiveinsatz von MySQL mag man streiten, aber um einfach mal anzufangen reicht MySQL völlig aus. Die Dateien für sehr viele Betriebsysteme stehen auf der <a href="http://dev.mysql.com/downloads/mysql/5.1.html">download Seite</a> bereit. Die Installation besteht eigentlich nur noch aus dem entpacken des tar.gz Archivs und starten der darin enthaltenen .pkg Datei. Eine <a href="http://dev.mysql.com/doc/refman/5.1/de/mac-os-x-installation.html">Anleitung</a> hat MySQL auch online gestellt.</p>
<p>Nachdem die Datenbank nun läuft ist es Zeit Locomotive zu starten. In der Applikation kann nun ein beliebiges Projekt erstellt werden (Apfel + N). Dazu gibt man den Namen und Pfad an, in dem das neue Projekt erstellt werden soll. Wer glücklicher Besitzer einer <a href="http://macromates.com/">Textmate</a> Lizens ist, klickt rechts auf das erstellt Projekt im Locomotive Fenster und wählt: &#8220;Edit in Textmate&#8221;. Es geht aber auch jeder andere Editor, um die wenigen Schritte zum laufenden Projekt zu gehen.</p>
<p>Die Datei <code>config/database.yml</code> im Projektverzeichnis enthält die Angaben, um Rails mit der Datenbank kommunizieren zu lassen. Hier sind in der bei der Verwendung von MySQL lediglich die Datenbanknamen für development, test und production anzugeben. Bei Bedarf kann hier auch der Benutzer, Passwort und Host bzw. Socket angepasst werden. Der schnellste Weg zu den drei Datenbanken ist mit Hilfe des Terminals:</p>
<pre lang="bash">mysql -uUser -pPasswort</pre>
<p>In der geöffneten mysql shell sind die drei create Anweisungen nötig</p>
<pre lang="sql">
create database projektname_development;
create database projektname_test;
create database projektname_production;</pre>
<p>So, das war es eigentlich schon. Nachdem mit Hilfe von Locomotive der Server für das Projekt gestartet wurde, sollte man im Browser unter der Adresse: <code>http://localhost:3000</code> eine Erfolgsmeldung sehen:</p>
<p><em>Welcome aboard. You’re riding the Rails!</em></p>
<div id="crp_related"><h3>Ähnliche Beiträge:</h3><ul><li><a href="http://www.christophbuente.de/2008-07-30-gepatchte-mysql-version-nuetzliche-features-schluesselfertig-eingebaut/" rel="bookmark" class="crp_title">Gepatchte MySQL Version &#8211; nützliche Features schlüsselfertig eingebaut</a></li><li><a href="http://www.christophbuente.de/2008-07-01-mysql-myisam-index-oder-nicht/" rel="bookmark" class="crp_title">MySQL MyISAM &#8211; Index oder nicht?</a></li><li><a href="http://www.christophbuente.de/2010-07-20-rails-hosting-bei-rocket-rentals-auch-mit-staging-umgebung/" rel="bookmark" class="crp_title">Rails Hosting bei Rocket Rentals &#8211; auch mit Staging Umgebung</a></li><li><a href="http://www.christophbuente.de/2007-11-24-advancing-rails-ein-workshop-mit-david-a-black/" rel="bookmark" class="crp_title">Advancing Rails &#8211; Ein Workshop mit David A. Black</a></li><li><a href="http://www.christophbuente.de/2007-10-05-frei-nehmen-um-zu-lernen/" rel="bookmark" class="crp_title">Rails tutorial &#8211;  Eine Woche lang Agile Webentwicklung</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.christophbuente.de/2007-11-25-ruby-on-rails-auf-mac-os-x-5-minuten-kurzanleitung/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Paypal subscriptions &#8211; Abonnements in Java integrieren</title>
		<link>http://www.christophbuente.de/2007-11-10-paypal-subscriptions-abonnements-in-java-integrieren/</link>
		<comments>http://www.christophbuente.de/2007-11-10-paypal-subscriptions-abonnements-in-java-integrieren/#comments</comments>
		<pubDate>Sat, 10 Nov 2007 14:48:10 +0000</pubDate>
		<dc:creator>Christoph Bünte</dc:creator>
				<category><![CDATA[Web Entwicklung]]></category>
		<category><![CDATA[abonnement]]></category>
		<category><![CDATA[anleitung]]></category>
		<category><![CDATA[buttonfactory]]></category>
		<category><![CDATA[exclude]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JEE]]></category>
		<category><![CDATA[paypal]]></category>
		<category><![CDATA[paypal subschription]]></category>
		<category><![CDATA[sandbox]]></category>
		<category><![CDATA[Software Entwicklung]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[zahlungsabwicklung]]></category>

		<guid isPermaLink="false">http://www.christophbuente.de/2007-11-10-paypal-subscriptions-abonnements-in-java-integrieren/</guid>
		<description><![CDATA[Für einen Kunden habe ich in der letzten Woche die Zahlungsabwicklung von Abonnements über Paypal integriert. Der Web Nutzer kann auf diesem einfachen Wege die Vorzüge vom Premiumdiensten nutzen. Der Vorteil hierbei ist: Der potentielle Käufer muss seine Kreditkarten- bzw. Kontodaten nicht an eine &#8220;nicht vertrauenswürdige&#8221; Seite weitergeben, sondern nutzt die bereits bei Paypal hinterlegten [...]]]></description>
			<content:encoded><![CDATA[<p>Für einen Kunden habe ich in der letzten Woche die Zahlungsabwicklung von Abonnements über <a href="http://www.paypal.de">Paypal</a> integriert. Der Web Nutzer kann auf diesem einfachen Wege die Vorzüge vom Premiumdiensten nutzen. Der Vorteil hierbei ist: Der potentielle Käufer muss seine Kreditkarten- bzw. Kontodaten nicht an eine &#8220;nicht vertrauenswürdige&#8221; Seite weitergeben, sondern nutzt die bereits bei <a href="http://www.paypal.de">Paypal</a> hinterlegten Daten. Ist der Käufer noch keine <a href="http://www.paypal.de">Paypal</a> Kunde, ist eine vorige Anmeldung allerdings notwendig.</p>
<p><span id="more-18"></span></p>
<p>Der grundlegende Mechanismus für Subscriptions ist denkbar einfach. An einer beliebigen Stelle in unserer Webapplikation wird der Benutzer per link oder submit button an die Paypal Seite geleitet. Alle relevanten Daten für die Zahlung werden entweder als GET Parameter (Link) oder POST Parameter (Button) übertragen. Dazu zählen vor allem folgende Angaben:</p>
<ul>
<li>Abonnementinterval (1 Tag, 4 Wochen oder 12 Monate)</li>
<li>Betrag pro Abonnementinterval</li>
<li>Währung</li>
<li>Paypal Id des Verkäufers</li>
<li>Rechnungsnummer</li>
<li>Automatische Verlängerung (ja/nein)</li>
<li>Beliebige zusätzliche Informationen</li>
</ul>
<p>Sollte der Benutzer noch kein Paypal Kunde sein, muss er sich bei Paypal erst registrieren. Um dies so einfach wie möglich zu gestalten können wir zusätzlich Benutzerinformationen mitsenden, die Paypal in das Registrierungsformular einfügt.</p>
<ul>
<li>Name, Nachname</li>
<li>Adress(Strasse, <abbr title="Postleitzahl">PLZ</abbr>, Stadt, Land)</li>
<li>Email Adresse</li>
</ul>
<p>Damit wir zum Testen unserer Applikation kein Vermögen hinblättern müssen, stellt Paypal eine sogenannte Sandbox zur Verfügung. Eine eigene <a href="https://developer.paypal.com">Developer Sandbox</a> kann man sich hier einrichten. Diese <a href="https://sandbox.paypal.com">Sandbox</a> stellt die kompletten Funktionen von Paypal zur Verfügung. Mit zwei Unterschieden: Es fließt kein echtes Geld und es gibt nur die Benutzer, die wir selbst angelegt haben. Um also einen Zahlungsfluss zu simulieren müssen in der Sandbox mindestens zwei Benutzer angelegt sein (Verkäufer und Käufer). Zum Erzeugen eines einfachen Bezahlknopfes  eignet sich die Paypal Button Factory, welche unter <a href="https://www.sandbox.paypal.com/us/cgi-bin/webscr?cmd=_merchant&amp;nav=3">Merchant Services</a> im Paypal Menü des Verkäufers erreichbar ist. Doch es gibt auch Gründe gegen einen statischen Bezahlknopf auf der Webseite. Angenommen wir wollen mehrere Abonnements verkaufen, die sich je nach Laufzeit im Preis unterscheiden. Wäre es da nicht besser ein eigenes Formular zu erstellen, welches dem Benutzer die komplette Auswahl unserer Produkte anzeigt? Nachdem sich der Benutzer für eines unserer Abonnements entschieden hat, überträgt er seine Auswahl per druck auf den Bezahlknopf. Unsere Webapplikation wertet diese Informationen aus und leitet den Benutzer per redirect auf die Paypal Seite um. Dazu muss die <acronym title="Uniform Resource Locator" lang="en">URL</acronym> mit sämtlichen Zahlungsinformationen dynamisch erzeugt werden. Hier eine Beispielimplementierung:</p>
<pre lang="java">public String getPurchaseUrl() throws EncoderException {
	StringBuffer urlBuffer = new StringBuffer("https://www.sandbox.paypal.com/cgi-bin/webscr");
	urlBuffer.append("?no_note=1"); // Abonnements unterstützen keine Notizen
	urlBuffer.append("&amp;a3=9.99"); // Der Preis des Abonnements
	urlBuffer.append("&amp;t3=M"); // Intervall Einheit = Monate
	urlBuffer.append("&amp;p3=1"); // Intervall Länge = 1 (Monat)
	urlBuffer.append("&amp;business=verkaeufer@deine.url.de"); // Die email adresse für den verkäufer account bei paypal
	urlBuffer.append("&amp;cmd=_xclick-subscriptions"); // Wir wollen eine abonnement
	urlBuffer.append("&amp;src=1"); // Abonnement verlängert sich automatisch
	urlBuffer.append("&amp;currency_code=EUR"); // Wir nehmen Zahlungen in Euro entgegen
	urlBuffer.append("&amp;invoice=Rechnungsnummer"); // Hier kann eine Rechnungsnummer vergeben werden
	urlBuffer.append("&amp;lc=DE"); // Die Zielseite soll in deutscher Sprache angezeigt werden
	urlBuffer.append("&amp;no_shipping=1"); // Wir brauchen keine Versandadresse, denn wir verkaufen virtuelle Güter oder Dienstleistungen
	URLCodec encoder = new URLCodec();
	return encoder.encode(urlBuffer.toString());
}</pre>
<p>Für das URL Encoding, welches alle Sonderzeichen in übertragbare Zeichen umwandelt, verwende ich die <a href="http://commons.apache.org/codec/">commons-codec Bibliothek</a> von <a href="http://commons.apache.org/">Apache Commons</a>.</p>
<p><!--adsense#vert-banner--></p>
<p>Die geladene Paypal Seite enthält nun alle Zahlungsinformationen. Der Potentielle Käufer muss sich lediglich mit seinem Paypal Benutzernamen anmelden und die Zahlung bestätigen. Ist die Automatische Rückleitung aktiviert, landet der Benutzer danach wieder auf unserer Seite. Die Aktivierung kann im Paypal Menu des Verkäufers unter &#8220;Profile -&gt;Website Payment Preferences&#8221; eingestellt werden. Dazu wählt man den Radiobutton &#8220;Auto Return ON&#8221; und trägt unter &#8220;Return URL&#8221; die entsprechende Url ein, an die der Benutzer weitergeleitet werden soll. Mit dieser URL überträgt Paypal eine Transaktions Id,  wenn in den Einstellungen zusätzlich noch &#8220;Payment Data Transfer&#8221; auf &#8220;On&#8221; gesetzt wurde. Die Dokumentation für <acronym title="Payment Data Transfer" lang="en">PDT</acronym> finden man auf der <a href="https://www.paypal.com/IntegrationCenter/ic_pdt.html">Paypal Developer Seite</a>. Paypal erwartet darauf hin, dass unsere Webapplikation folgende Informationen zurück sendet:</p>
<ul>
<li>TransaktionsId</li>
<li>Identitätstoken</li>
<li> Kommando</li>
</ul>
<p>Die TransaktionsId ist die eben empfangene Id. Der Identitätstoken kann an der Stelle eingesehen werden, wo &#8220;Payment Data Transfer&#8221; angeschaltet wurde. Dies stellt sicher, dass  Zahlungsinformationen nicht an unberechtigte Personen gesendet werden. Das Kommando muss den den Wert &#8220;_notify-synch&#8221; enthalten. Hier ein Beispiel, wie die Implementierung aussehen könnte. Für den Post Request zurück an Paypal habe ich die <a href="http://jakarta.apache.org/httpcomponents/httpclient-3.x/">commons-httpclient Bibliothek</a> von <a href="http://commons.apache.org/">Apache Commons</a> verwendet.</p>
<pre lang="java">/**
 * Verabeitet Paypals Payment Data Transfer
 *
 * @param txId The transactionId
 * @return
 */
public void handleCallback(long txId) {
	Map&lt;String,Object&gt; params = new HashMap&lt;String, Object&gt;();
	params.put("cmd","_notify_synch");
	params.put("tx", txId);
	params.put("at", "IDENTITY_TOKEN");
	try {
		PostMethod method = doPostRequest("https://www.sandbox.paypal.com/cgi-bin/webscr", params);
		String responseBody = method.getResponseBodyAsString();
		if(responseBody != null) {
			if(responseBody.startsWith("SUCCESS")) {
				// Super, alles hat geklappt
				// Erfolgsnachricht anzeigen
			} else if(responseBody.startsWith("FAIL")) {
				// Die Zahlung war nicht korrekt durchgeführt
				// Fehlernachricht anzeigen
			} else {
				// Irgendwas ging richtig in die Hose
				// Fehlerbehandlung
			}
		} else {
 			// Das war auch nicht korrekt
	 		// Fehlerbehandlung
 		}
	} catch (HttpException e) {
		// Error sending PDT response
	} catch (IOException e) {
		// Error sending PDT response
	}
}
/**
 * Does a POST request to the given url and the given parameter map
 *
 * @param url
 * @param params
 * @return The method containing the response
 * @throws HttpException
 * @throws IOException
 */
public PostMethod doPostRequest(String url, Map&lt;String, Object &gt; params)
 	throws HttpException, IOException {
		HttpClient client = new HttpClient();
		HttpConnectionManager conManager = client.getHttpConnectionManager();
		HttpClientParams clientParams = client.getParams();
		clientParams.setConnectionManagerTimeout(2000);
		HttpConnectionManagerParams managerParams = conManager.getParams();
		managerParams.setConnectionTimeout(5000);
		managerParams.setSoTimeout(5000);
		PostMethod method = new PostMethod();
		method.setURI(new URI(url, false));
		HttpMethodParams paramsM = method.getParams(); // Wiederholungen unterdrücken
		paramsM.setParameter(HttpMethodParams.RETRY_HANDLER,
	 		new DefaultHttpMethodRetryHandler(0, false));
	Set&lt;String&gt; keys = params.keySet();
	for (String key : keys) {
		String value = (String) params.get(key);
		method.addParameter(key, value); // Setze Url Parameter
	}
	client.executeMethod(method); // Http Post ausführen
	return method;
}</pre>
<p>Der Benutzer merkt vom Austausch der Zahlungsinformationen nichts, Es wird lediglich eine einfache Bestätigungsseite angezeigt. Auf dieser Seite wird dem Benutzer mitgeteilt wird, dass die Zahlung erfolgreich oder nicht erfolgreich war, und dass er von Paypal per Mail darüber benachrichtigt werden wird.</p>
<p>Paypal bietet zusätzlich die Möglichkeit, unsere Webapplikation asynchron über eingehende Zahlungen und/oder Kündigungen zu informieren. Die Mechanismus nennt sich <acronym title="Instant Payment Notification" lang="en">IPN</acronym>, was soviel bedeutet wie &#8220;sofortige Zahlungsavisierung&#8221;. Dieser Mechanismus ist deutlich robuster, als &#8220;Payment Data Transfer&#8221;. Doch dazu in später mehr.</p>
<div id="crp_related"><h3>Ähnliche Beiträge:</h3><ul><li><a href="http://www.christophbuente.de/2007-10-23-bots-aussperren-mit-captcha/" rel="bookmark" class="crp_title">captcha tutorial &#8211; Bots aussperren</a></li><li><a href="http://www.christophbuente.de/2009-10-29-opensocial-gadgets-apps-fur-studivz-selbst-entwickeln/" rel="bookmark" class="crp_title">Opensocial Gadgets &#8211; Apps für StudiVZ selbst entwickeln</a></li><li><a href="http://www.christophbuente.de/2008-01-24-stripes-framework-tests-fur-actionbeans-im-wizard-modus/" rel="bookmark" class="crp_title">Stripes Framework &#8211; Tests für ActionBeans im Wizard Modus</a></li><li><a href="http://www.christophbuente.de/2007-11-17-canoo-webtest-web-anwendungen-automatisch-testen/" rel="bookmark" class="crp_title">canoo webtest &#8211; Web-Anwendungen automatisch testen</a></li><li><a href="http://www.christophbuente.de/2009-09-09-500-internal-server-error-apache-config-vs-wp-super-cache/" rel="bookmark" class="crp_title">500 Internal Server Error &#8211; Apache config vs. WP-Super-Cache</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.christophbuente.de/2007-11-10-paypal-subscriptions-abonnements-in-java-integrieren/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using memcached (Feed is rejected)
Page Caching using memcached
Database Caching 8/37 queries in 0.054 seconds using memcached
Object Caching 1123/1214 objects using memcached

Served from: www.christophbuente.de @ 2012-02-07 08:48:01 -->
