Recent Updates RSS Toggle Comment Threads | Keyboard Shortcuts

  • Daniel Bartl 13:14 on 21 August, 2010 Permalink | Reply  

    Java 4-ever 

    One of the most compelling dramas of our time ;)

     
  • Tomislav Zorc 17:35 on 30 June, 2010 Permalink | Reply
    Tags: , , , ,   

    Community-Firma 

    Swiss-Re spricht es klar aus: Das Unternehmen als eine real existierende Community braucht die elektronische Abbildung, um den Informationsfluß zwischen den Mitarbeitern im komplexen Marktgeschehen auf Hochtouren zu bringen.

    http://www.cio.de/strategien/methoden/2235769/?qle=rssfeed_

    Langfristiger Markterfolg und keine kurzfristigen ROI-Betrachtungen werden Swiss-Re Recht geben!

     
  • Daniel Bartl 23:36 on 28 June, 2010 Permalink | Reply  

    Agiler Firmenausflug zum Bodensee 

    Anbei ein paar Fotos von unserem letzten Firmenausflug zum Bodensee. Es war ein wunderschöner Segelausflug und ein entspannendes, nicht allzu windiges, aber dafür ein sehr sonniges Wochenende, das wir auf 3 Segelbooten verbringen durften. Ungefähr genauso wie es auch sein sollte, damit alle Geeks wieder heil nach Hause zurückkommen ;)

    Leider dürfen wir keine unserer vielen Videoaufnahmen hier veröffentlichen, weil wir inzwischen alle Rechte an diesen an Disney abgetreten haben. Als Gegenleistung hat Disney daraus aber diesen tollen Film für uns gemacht.

     
  • Peter Dmytrasz 17:45 on 16 June, 2010 Permalink | Reply
    Tags: software, , , , Agil, Softwareentwicklung   

    Agiles Projektmanagement mit Scrum 

    Zur Einleitung eine Metapher eines Softwareentwicklungsprojekts mit seinen jeweiligen Akteuren

    Was ist Scrum eigentlich?

    Nun ja, die Bedeutung von Scrum kann man auf zwei unterschiedliche Weisen erläutern. Einerseits ist Scrum definiert als agiles – also flexibles – Projektmanagementverfahren welches hauptsächlich in Softwareentwicklungsprojekten eingesetzt wird. Hierbei wird viel Wert auf Wissensmanagement – sprich die Weiterbildung der Mitarbeiter – gelegt. Der eigentliche Prozess besteht aus mehreren, verschachtelten Schleifen – sogenannten Sprints – in denen Feedback an den Projektleiter – ScrumMaster – zu bisherigen Ergebnissen gegeben wird. Andererseits ist Scrum einfach die deutsche Übersetzung für „Gedränge“, was möglicherweise mit den zahlreichen Projektmitgliedern und deren Koordination in einem Scrum-Projekt zu tun hat.

    Entwickelt wurde Scrum durch Ken Schwaber, Jeff Sutherland und Mike Beedle. Beide haben das Vorgehensmodell erstmals 1995 auf der OOPSLA (Object-Oriented Programming, Systems, Languages & Applications) in den USA vorgestellt und in den folgenden Jahren etabliert.

    Aufgrund ihrer mangelnden Flexibilität sind die meisten Projektmanagement-Methode für Softwareentwicklungs-Projekte nur beschränkt geeignet. Abhängigkeiten zwischen einzelnen Teams oder Akteuren legen einen starren Zeitplan vor und verhindern Parallelarbeiten. Zusätzlich werden Prozesse, Pläne und Dokumentationen in klassischen Phasenmodellen hoch priorisiert, was wenig Raum für Kreativität und Innovationen lässt.

    Im Februar 2001 wurde das Agile Manifest veröffentlicht, welches Werte für die Agile Softwareentwicklung enthält. Dieses Dokument bildet das Fundament der Prozessdefinition von Scrum. Das Agile Manifesst enthält folgende Kernpunkte:

    1. Individuen und Interaktionen gelten mehr als Prozesse und Tools.
    2. Funktionierende Programme gelten mehr als ausführliche Dokumentation.
    3. Die stetige Zusammenarbeit mit dem Kunden steht über Verträgen.
    4. Der Mut und die Offenheit für Änderungen steht über dem Befolgen eines festgelegten Plans.


    Welche Rollen existieren in Scrum-Projekten?

    In einem Scrum-Projekt agieren viele Protagonisten miteinander, um den Projekterfolg zu garantieren. Für Gewöhnlich werden nur drei Rollen in Scrum-Projekten definiert (ScrumMaster, Team und Product Owner). Boris Gloger erweitert dieses Modell jedoch um die Akteure Manager, Customer und End User. Dieses Szenario wird im Folgenden vorgestellt und um diese Rollen sowie deren Verknüpfungen verständlicher darzustellen, wird hier die Metapher einer Filmproduktion verwendet.

    1. ScrumMaster – Der Regisseur
    Der ScrumMaster ist der Leiter des Teams und der Moderator der regelmäßigen Meetings. Er muss das Team vor von Außen einwirkenden Faktoren beschützen, die den Projektverlauf gefährden oder behindern könnten. Seine Aufgabe ist weiterhin, dass die agilen Richtlinien eingehalten und umgesetzt werden. Auf diese Weise steigert er die Produktivität seines Teams.

    2. Team – Die Schauspieler
    Das Team liefert das Endprodukt ab und ist verantwortlich für dessen Qualität. Die Anforderungen des Kunden und der End User werden aufgenommen und analysiert und im Anschluss daran umgesetzt. Im Grunde wird alles, das Design, die Funktionalitäten, die Tests, etc., vom Team implementiert und durchgeführt. Hierzu ist eine enge Zusammenarbeit mit dem Product Owner notwendig, um die strategische Ausrichtung des Softwareentwicklungsprojekts stetig neu zu definieren.

    3. Manager – Der Studioboss
    Das Management ermöglicht eine angemessene Umgebung für das Scrum-Team, definiert Strukturen und erzeugt Stabilität. Es arbeitet eng mit dem ScrumMaster zusammen um die Richtlinien, falls nötig, neu zu skizzieren.

    4. Customer – Der Produzent
    Der Kunde ist typischerweise die Person, welche vom Scrum-Team das finale Endprodukt überreicht bekommt. Kunden sind meist Manager in Unternehmen, welche externe Organisationen damit beauftragen, Produkte für sie zu entwickeln.

    5. Product Owner – Der Drehbuchautor
    Der Product Owner hat in gewissem Sinne die Unternehmens-Brille auf. Er hat eine klare Vision, wie das Produkt aussehen soll und welche Haupt-Charakteristika es erfüllen soll. Nach jedem Sprint wird das Ergebnis durch ihn begutachtet und abgenommen. Die Hauptaufgabe des Product Owners ist es sicherzustellen, dass das Team nur an den, für die Organisation wichtigsten Backlog Items arbeitet und sie dazu mit den notwendigen Informationen zeitnah zu versorgen. Er ist verantwortlich für den Return on Investment – also die Rentabilität.

    6. End User – Das Publikum
    Der End User kann anhand vieler, verschiedener Rollen definiert werden. Er kann eine Person aus der Marketing-Abteilung sein, ein Consultant oder ein Domain-Experte. Die Liste ließe sich beliebig lang erweitern, doch der Punkt ist, der End User kennt die Anforderungen, weil er sie selbst aufgestellt hat. Somit hat er eine gewisse Erwartungshaltung gegenüber dem Produkt und eine fundierte Wissensbasis in dessen Einsatzgebiet. Dieses Wissen gibt er an das Team weiter, welche es für die Umsetzung nutzen sollte.


    Welche Artefakte gibt es in Scrum?

    Um ein Scrum-Projekt erfolgreich abzuschließen, bedienen sich Scrum-Teams sogenannter Artefakte. Das sind Tools oder Ergebnisse von Aktivitäten welche im Projekt eine professionelle Arbeitsgestaltung ermöglichen. Die effizienteste und effektivste Form der Kommunikation in Projekten ist nach wie vor die face to face-Kommunikation, so dass in diesem Sinne Artefakte mit anderen Kommunikationsformen durch diese ersetzt werden. Die agile Softwareentwicklung beinhaltet ein Artefakt, auf das unter keinen Umständen verzichtet werden kann, nämlich auslieferbaren Code. Da sich die Film-Metapher auch hier zum näheren Verständnis eignet, wird sie auch auf diese Thematik angewendet.

    1. Impediment Backlog – Die Fehlerliste
    In dieser Liste werden Hindernisse und Risiken aufgezeichnet, welche dem Scrum-Team Probleme bereiten könnten. Dem ScrumMaster dient Auflistung dazu, seine nächsten Aktionen zu planen um diese Barrieren zu minimieren oder zu beseitigen.

    2. Product Backlog – Das Drehbuch
    Im Product Backlog werden Geschichten, Anforderungen, Funktionalitäten, etc. notiert. Diese Liste entspricht im Grunde einem Katalog an Kriterien, welche das Scrum-Team in Zukunft abliefern möchte. Die Backlog Items dieses Dokuments sind nach dem Wert für das Unternehmen und der Kapitalrendite (Return on Investment) sortiert.

    3. Selected Product Backlog – Die Szenen
    Eine Szene ist ein Teil des gesamten Films. So etwa kann man auch das Selected Product Backlog verstehen. Hier werden die Spezifikationen des Product Backlog aufgelistet, welche für den aktuellen Sprint umgesetzt werden müssen.

    4. Potential Shippable Product Increment – Eine Episode
    Am Ende eines Sprints liefert das Scrum-Team ein potentiell lieferfähiges Produkt-Inkrement ab, an dem nicht mehr gearbeitet werden muss. Falls die Entwicklung zu diesem Zeitpunkt eingestellt werden müsste, ist das ein bereits funktionsfähiger Teil des Prototypen, der bereits eingesetzt werden könnte.

    5. Sprint Backlog – Der eigentliche Dreh
    Der Sprint Backlog visualisiert die nächsten Aktivitäten für das Entwicklerteam und hilft dabei, diese zu synchronisieren, da das bei einer größeren Anzahl sehr schnell sehr unübersichtlich werden kann. Man muss aber immer im Hinterkopf behalten, dass anhand des Sprint Backlogs keine Vortschritte, sondern lediglich der aktuelle Status, bzw. die momentane Situation veranschaulicht werden.


    Wie funktioniert das Tracking des Fortschritts in Scrum?

    Hierbei dient einerseits das Burn Down Chart als bewährte Methode um Fortschritte zu visualisieren. Dies geschieht unüblicherweise durch das Team selbst. Jeweils ein Burn Down Chart wird für jeden Sprint hergenommen und täglich aktualisiert. Dabei repräsentiert die vertikale Achse die Anzahl der abzuarbeitenden Tasks und die horizontale Achse die Tage des aktuellen Sprints. Bei der Erstellung eines Burn Down Charts, sollte man besonders darauf achten, es einfach zu gestalten damit das Team die regelmäßigen Updates leicht eintragen kann.

    Auf der anderen Seite kann man ergänzend zum Burn Down Chart noch das Task Board verwenden, um den Status des aktuellen Sprints festzuhalten. Hier gilt die selbe Regel wie beim Burn Down Chart, dass nur das Scrum-Team das Task Board pflegt und benutzt. Dieses Task Board kann entweder ein Software-Tool sein oder ein Whiteboard an der Wand.

    Das Task Board lässt sich in vier Spalten unterteilen.

    1. Selected Product Backlog (Stories)
    Hier werden alle Product Backlog Items / Stories eingetragen, welche das Team in diesem Sprint erledigen möchte. Dabei wird – zur besseren Übersicht – auch gleich eine Priorisierung von Wichtigem nach Unwichtigem angewandt.

    2. Tasks To Do
    Die Tasks die noch nicht gestartet wurden aber noch erledigt werden müssen, haben ihren Platz in dieser Spalte. Sie ergeben sich aus den Sprint Planning Meetings oder während man den Sprint ausführt.

    3. Work in Progress
    Sobald ein Teammitglied einen Task beginnt, nimmt er die Karte mit diesem Task und bringt sie in der Spalte Work in Progress an. Ist eine Aufgabe seit dem letzten Daily Scrum in dieser Spalte, erhält sie eine Markierung, für gewöhnlich mit einem roten Punkt. Bleiben Tasks länger als einen Tag in Bearbeitung, kann man sie auch in Untertasks aufteilen. Verhindert etwas die Erfüllung eines bestimmten Tasks, wird die Karte auch mit einem roten Punkt markiert und das Hindernis dazu geschrieben.

    4. Done
    Sobald ein Task erledigt ist, wird die Karte vom jeweiligen Teammitglied in der Spalte Done angebracht. Im Anschluss daran wird die nächste Aufgabe in Angriff genommen. Was als „erledigt“ definiert wird kann vorher in einem Brainstorming spezifiziert werden.


    Welche Meetings gibt es in Scrum-Projekten?

    Wie in jedem gut organisierten Projekt ist ein guter Zeitplan das A und O und macht so einen Großteil des Erfolges aus. In Scrum wird das Projekt über den kompletten Zeitraum von einer Vielzahl unterschiedlicher Meetings und Meeting-Typen begleitet. Welche das sind, wird anhand folgender Grafik veranschaulicht und im Anschluss erläutert.

    1. Estimation Meeting
    Den Beginn eines jeden Sprints leitet das Estimation Meeting ein. Es dient dazu die Backlog Items und deren Größe kennenzulernen. Dabei schätzt das Team selbst ab, wieviel Arbeit es sich zumutet, so dass ein Optimum gefunden wird. Die Teammitglieder bekommen weiterhin einen Überblick darüber, was sie in den nächsten Projektphasen erwartet.

    2. Sprint Planning Meeting – Part 1
    Das Ziel des ersten Sprint Planning Meetings ist herauszufinden was der End User im Detail haben möchte. Dadurch haben die Entwickler ein klares Bild davon, was der End User braucht und somit, was implementiert werden soll.

    3. Sprint Planning Meeting – Part 2
    Im zweiten Teil des Sprint Planning Meetings geht es hauptsächlich um das Design der zu implementierenden Lösung. Am Ende dieses Meetings weiß das Entwicklerteam wie die benötigten Funktionalitäten umgesetzt werden können.

    4. Daily Scrum
    Das Daily Scrum ist ein relativ kurzer Statusbericht jedes Teams, in dem der aktuelle Stand sowie Hindernisse mit dem ScrumMaster besprochen werden. Dieser Termin findet – wie der Name bereits erahnen lässt – jeden Tag statt und dabei werden die täglichen Aktivitäten geplant. Als hilfreiche Tool lassen sich hier das Task Board und das Burn Down Chart empfehlen.

    5. Sprint Review
    Am Ende eines jeden Sprints wird dem End User im Rahmen des Sprint Review das aktuelle Ergebnis präsentiert und im Anschluss daran eine Feedbackrunde an das Entwicklerteam angesetzt. Die Rückmeldung nutzt das Scrum-Team nun um neue Backlog Items zu erstellen oder bestehende zu modifizieren.

    6. Sprint Retrospective
    Dieses letzte Meeting kann mit einer medizinischen Diagnose des Ergebnisses verglichen werden. Hier gilt es Themen zu finden bei denen Verbesserungsbedarf besteht. Dies lässt sich gut mit zwei Flipcharts machen, auf denen die Überschirften „What went well?“ und „What could be improved?“ notiert sind. Nun schreiben die Teammitglieder ihre Ideen dazu auf Post-Its und füllen so die Flipcharts, welche im Anschluss diskutiert werden.


    Wo liegt der Unterschied zwischen Scrum und anderen Vorgehensmodellen im Projektmanagement?

    Wie wir bereits im ersten Kapitel gelernt haben, ist Scrum ein agiles Projektmanagement-Vorgehensmodell. Das bedeutet, dass die Kreativität und Flexibilität der Mitarbeiter gefördert werden soll indem Regeln und bürokratische Aufwände auf ein Minimum reduziert werden. Die Frage nach dem richtigen Vorgehensmodell lässt sich ganz einfach beantworten, wenn man darüber nachdenkt was der Output des Projekts sein wird.  Hierzu soll uns das Beispiel der Schiffsentwicklung dienen. Inwiefern würde sich Scrum in einem solchen Vorhaben eignen? Nehmen wir an die Schiffbau-Ingeneure treffen sich täglich zu ihrem Daily Scrum Meeting und pflegen ein Task Board. Dabei können die meisten Arbeiter noch gar nicht beginnen, weil das Design des Schiffs noch nicht fertig ist. Das hat schließlich Auswirkungen auf Faktoren wie Material und Technik. Ist dieser Punkt abgeschlossen können die Mitarbeiter der Materialbeschaffung loslegen und werden die Teile geliefert ist als nächstes die Montage an der Reihe. Hierbei handelt es sich um ein klassisches Wasserfallmodell. Sobald ein Mitarbeiter seine Aufgabe abschließt, beginnt der nächste mit seiner.

    In der Softwareentwicklung eignet sich ein solches Verfahren nicht, da meist Parallelarbeit möglich ist. Das ist das Spielfeld auf dem Scrum spielt. Es gibt jedoch weitere anerkannte Modelle in der Softwareentwicklung. Extreme Programming ist – wie Scrum – ein Vertreter der agilen Softwareentwicklung. Dabei werden fortlaufende Iterationen betrachtet, die eine schrittweise Annäherung an die Anforderung des Kunden zum Ziel haben.

    Das Spiralmodell ist – im Gegensatz zu Scrum – kein agiles, sondern ein generisches Vorgehensmodell in der Softwareentwicklung. Dieses Modell muss man sich als Spirale welche in vier Quadranten aufgeteilt ist, vorstellen. Die vier Abschnitte beschreiben die Festlegung der Ziele, die Risikoanalyse, die Entwicklung und Test sowie die Planung des nächsten Zyklus. Das Ende jeder Iteration beschließt immer ein Prototyp.

    Das V-Modell lässt sich nicht so leicht in eine Schublade zu generischen oder agilen Softwareentwicklungs-Vorgehensmodellen stecken da es Elemente beider Arten in sich vereint. Die Hauptmerkmale des V-Modells sind im absteigenden Ast die Spezifikation und die immer feinere Darstellung und im aufsteigenden Ast die Realisierung und Integration.


    Warum ist Scrum wirtschaftlicher als andere Methoden?

    Ist es nicht! Im Projektmanagement ist es wichtig immer das richtige Tool für eine bestimmte Aufgabe zu wählen. Manchmal ist Scrum genau das passende Werkzeug um das Projekt bestmöglich abzuschließen, allerdings gibt es Situationen in denen das eben nicht der Fall ist. Den größten Erfolg kann man in gewissen Projekten möglicherweise mit anderen agilen Vorgehensmodellen haben oder gar mit generischen wie dem Wasserfallmodell. So pauschal lässt sich das nicht sagen. Mit Scrum wurde hier ein sehr guter Ansatz vorgestellt, aber nicht die Universallösung für Softwareentwicklungsprojekte. Es erfreut sich momentan größter Beliebtheit und hat sich schon des öfteren als eines der besten Agilen Projektmanagement-Verfahren bewährt. Wenn man versucht einen Trend für die nächsten Jahre zu erkennen, so wird dieser ganz sicher in Richtung Agilität gehen.


    Quellen

    http://borisgloger.com/2008/07/23/scrum-rollen-das-team/
    http://de.wikipedia.org/wiki/Scrum
    http://scrum-fibel.de/
    http://www.controlchaos.com/
    http://www.scrum.org/
    http://en.wikipedia.org/wiki/Ken_Schwaber
    http://slides.liip.ch/scrum-liip-techtalk-20080923/title.html
    http://de.wikipedia.org/wiki/Agile_Softwareentwicklung
    http://de.wikipedia.org/wiki/Vorgehensmodell_zur_Softwareentwicklung
    http://projektmanagement-definitionen.de/scrum-naechste-generation-projektmanagements/
    http://de.wikipedia.org/wiki/Extreme_Programming
    http://de.wikipedia.org/wiki/Spiralmodell

     
  • Daniel Bartl 17:11 on 4 June, 2010 Permalink | Reply
    Tags: Pair Programming, Spring, TDD, wicket   

    Test Driven Development With Apache Wicket And Spring Framework 

    Since the development of our own web applications is mostly based on a Spring framework for dependency injection and application configuration in general and Apache Wicket framework as a truly component-oriented web framework for the MVC part of building a web application, it’s especially important for us to get these two frameworks running together smoothly not only when deployed on a running server instance itself but rather during the execution of our JUnit based integration tests as well. Thanks to the WicketTester API provided by the Wicket framework itself, one can easily build high-quality web applications while practicing test driven development and providing a decent set of unit and integration tests to be executed with each build. As already mentioned previously, integration and configuration of our web applications is based on a lightweight Spring container meaning that the integration of Spring’s ApplicationContext and a WicketTester API is essential to get our integration tests running. In order to best explain how to achieve that integration in an easy and elegant fashion in your integration test environment, we’ll first take a look at a configuration of these 2 framework beauties in a runtime environment.

    Configuration of the runtime environment

    In order to get Wicket framework up to speed when your server is up and running, you usually configure an according WicketFilter instance in your web application deployment descriptor file (web.xml) while passing it a single init parameter called applicationClassName that points to your main implementation class extending org.apache.wicket.protocol.http.WebApplication where all of your application-wide settings and initialization requirements are dealt with:

    <filter>
        <filter-name>wicketfilter</filter-name>
        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
        <init-param>
            <param-name>applicationClassName</param-name>
            <param-value>com.comsysto.webapp.MyWebApplication</param-value>
        </init-param>
    </filter>
    

    In case you want to get Wicket application up and running while leaving the application configuration and dependency injection issues to the Spring container, the configuration to be provided within the deployment descriptor looks slightly different though:

    <web-app>
        <filter>
            <filter-name>wicketfilter</filter-name>
            <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
            <init-param>
                <param-name>applicationFactoryClassName</param-name>
                <param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value>
            </init-param>
        </filter>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <context-param>
            <param-name>contextConfigLocation<param-name>
            <param-value>/WEB-INF/applicationContext.xml<param-value>
        </context-param>
    </web-app>
    

    The additional configuration part containing listener and context parameter definition is a usual, purely Spring container related configuration detail. ContextLoaderListener is an implementation of standard Servlet API ServletContextListener interface provided by the Spring framework itself and is responsible for looking up an according bean definition file(s) specified by the context param above and creating an ApplicationContext instance during servlet context initialization accordingly. When integrating an ApplicationContext instance with Wicket framework, one of the beans defined in the above mentioned Spring bean definition file has to be your own specific extension of org.apache.wicket.protocol.http.WebApplication. You can either define an according bean in the bean definition file itself:

    <beans>
        <bean id="myWebApp" class="com.comsysto.webapp.MyWebApplication"/>
    </beans>
    

    or use powerful classpath scanning feature of the Spring framework and annotate the MyWebApplication implementation with the appropriate @Component annotation accordingly while enabling the Spring container to scan the according package(s) of your application for relevant bean definitions:

    <beans>
        <context:component-scan base-package="com.comsysto.webapp" />
        <context:component-scan base-package="com.comsysto.webapp.service" />
        <context:component-scan base-package="com.comsysto.webapp.repository" />
    </beans>
    

    Either way, if everything goes well, you’ll get a pre-configured ApplicationContext all set up during the startup of your web container. One of the beans in the ApplicationContext will be your own extension of Wicket’s WebApplication type. SpringWebApplicationFactory implementation provided by the Wicket framework itself that you have defined as the applicationFactoryClassName in the configuration of your WicketFilter will then be used in order to retrieve that very same WebApplication bean out of your Spring ApplicationContext. The Factory expects one and only one extension of Wicket’s very own WebApplication type to be found within the ApplicationContext instance at runtime. If no such bean or more than one bean extending WebApplication is found in the given ApplicationContext an according IllegalStateException will be raised and initialization of your web application will fail:

    Map<? , ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(ac,WebApplication.class, false, false);
    if (beans.size() == 0)
    {
    	throw new IllegalStateException("bean of type [" + WebApplication.class.getName() +
    			"] not found");
    }
    if (beans.size() > 1)
    {
    	throw new IllegalStateException("more than one bean of type [" +
    			WebApplication.class.getName() + "] found, must have only one");
    }
    

    After the WebApplication bean has been successfully retrieved from the ApplicationContext via SpringWebApplicationFactory, WicketFilter will then, as part of its own initialization process, trigger both internalInit() and init() methods of the WebApplication bean. The latter one is the exact spot where the last piece of the runtime configuration puzzle between Wicket and Spring is to be placed :

    @Component
    public class MyWebApplication extends WebApplication {
        @Override
        protected void init() {
            addComponentInstantiationListener(new SpringComponentInjector(this));
        }
    
    }
    

    SpringComponentInjector provided by the Wicket framework enables you to get dependencies from the ApplicationContext directly injected into your Wicket components by simply annotating these with the according @SpringBean annotation.

    Configuration of the JUnit based integration test environment

    One of the main features of Apache Wicket framework is the ability to easily write and run plain unit tests for your Pages and all other kinds of Components that even include the verification of the rendering process itself by using JUnit framework and the WicketTester API only. When using Spring framework for application configuration together with Wicket, as we do, you can even use the same tools to easily write and run full blown integration tests for your web application as well. All you have to do is use Spring’s TestContext framework additionally to configure and run your JUnit based integration tests. The Spring Framework provides a set of Spring specific annotations that you can use in your integration tests in conjunction with the TestContext framework itself in order to easily configure an according ApplicationContext instance for your tests as well as for appropriate transaction management before, during and after your test execution. Following code snippet represents a simple JUnit 4 based test case using Spring’s specific annotations in order to initialize an ApplicationContext instance prior to executing the test itself:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:WEB-INF/applicationContext.xml"})
    @TransactionConfiguration(transactionManager = "txManager", defaultRollback = false)
    public class LoginPageTest {
    
        private WicketTester tester;
    
        @Autowired
        private ApplicationContext ctx;
    
        @Autowired
        private MyWebApplication myWebApplication;
    
        @Before
        public void setUp() {
            tester = new WicketTester(myWebApplication);
        }
    
        @Test
        @Transactional
        @Rollback(true)
        public void testRenderMyPage() {
            tester.startPage(LoginPage.class);
            tester.assertRenderedPage(LoginPage.class);
            tester.assertComponent("login", LoginComponent.class);
        }
    }
    

    By defining three annotations on the class level (see code snippet above) in your test, Spring’s TestContext framework takes care of preparing and initializing an ApplicationContext instance having all the beans defined in the according Spring context file as well as the transaction management in case your integration test includes some kind of database access. Fields marked with @Autowired annotation will be automatically dependency injected as well so that you can easily access and use these for your testing purposes. Since MyWebApplication, which extends Wicket’s WebApplication type and represents the main class of our web application, is also a bean within the ApplicationContext managed by Spring, it will also be provided to us by the test framework itself and can be easily used in order to initialize a WicketTester instance later on during the execution of the test’s setUp() method. With this kind of simple, annotation based test configuration we are able to run an integration test that verifies whether a LoginPage gets started and initialized, whether the rendering of the page runs smoothly and whether the page itself contains a LoginComponent that we possibly need in order to process user’s login successfully.

    When you run this test though, you’ll get the following exception raised unfortunately:

    
    java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
    	at org.springframework.web.context.support.WebApplicationContextUtils.getRequiredWebApplicationContext(WebApplicationContextUtils.java:84)
    	at org.apache.wicket.spring.injection.annot.SpringComponentInjector.<init>(SpringComponentInjector.java:72)
    	at com.comsysto.serviceplatform.uiwebapp.MyWebApplication.initializeSpringComponentInjector(MyWebApplication.java:59)
    	at com.comsysto.serviceplatform.uiwebapp.MyWebApplication.init(MyWebApplication.java:49)
    	at org.apache.wicket.protocol.http.WicketFilter.init(WicketFilter.java:719)
    	at org.apache.wicket.protocol.http.MockWebApplication.<init>(MockWebApplication.java:168)
    	at org.apache.wicket.util.tester.BaseWicketTester.<init>(BaseWicketTester.java:219)
    	at org.apache.wicket.util.tester.WicketTester.<init>(WicketTester.java:325)
    	at org.apache.wicket.util.tester.WicketTester.<init>(WicketTester.java:308)
    

    As you can see above, the Exception gets raised during the initialization of the WicketTester instance even before the actual test method gets executed. Even though we have applied rather cool and simple annotation based test configuration already described and passed in perfectly well prepared ApplicationContext instance to the WicketTester instance in the constructor, somewhere down the rabbit hole someone complained that no WebApplicationContext instance could have been found which seems to be required in order to initialize the WicketTester properly.

    Illegal State Sequence

    Illegal State Sequence

    The problem that we run against here is due to the fact that SpringComponentInjector during its own initialization is trying to get hold of an according Spring’s ApplicationContext instance that would normally be there in a runtime environment but does not find any since we are running in a test environment currently. SpringComponentInjector delegates to Spring’s own WebApplicationContextUtils class to retrieve the instance of ApplicationContext out of the ServletContext which is perfectly fine for a runtime environment but is unfortunately failing in a test environment:

    public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc)
    		throws IllegalStateException {
    
    	WebApplicationContext wac = getWebApplicationContext(sc);
    	if (wac == null) {
    		throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
    	}
    	return wac;
    }
    

    If you still remember we defined a ContextLoaderListener in our web.xml file as part of the configuration of our runtime environment that makes sure an according WebApplicationContext instance gets initialized and registered against the ServletContext properly. Luckily, this problem can easily be solved if we slightly change the way we initialize SpringComponentInjector in our main MyWebApplication class. Apart from the constructor that we have used so far, there is another constructor in the SpringComponentInjector class that expects the caller to provide it with an according ApplicationContext instance rather than trying to resolve one on its own:

    public SpringComponentInjector(WebApplication webapp, ApplicationContext ctx,
    		boolean wrapInProxies)
    {
    	if (webapp == null)
    	{
    		throw new IllegalArgumentException("Argument [[webapp]] cannot be null");
    	}
    
    	if (ctx == null)
    	{
    		throw new IllegalArgumentException("Argument [[ctx]] cannot be null");
    	}
    
    	// store context in application's metadata ...
    	webapp.setMetaData(CONTEXT_KEY, new ApplicationContextHolder(ctx));
    
    	// ... and create and register the annotation aware injector
    	InjectorHolder.setInjector(new AnnotSpringInjector(new ContextLocator(), wrapInProxies));
    }
    

    In order to use this constructor instead of the one we used previously, we now obviously need to get hold of the ApplicationContext instance on our own in our MyWebApplication implementation. The easiest way to do this is to use Spring’s own concept of lifecycle callbacks provided to the beans managed by the Spring container. Since our MyWebApplication is also a bean managed by the Spring container at runtime (enabled by the classpath scanning and @Component annotation on a type level), we can declare it to implement ApplicationContextAware interface which ensures that it gets provided with the ApplicationContext instance that it runs in by the Spring container itself during startup.

    public interface ApplicationContextAware {
    
    	void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
    
    }
    

    So the relevant parts of MyWebApplication type will now look something like the following code snippet:

    @Component
    public class MyWebApplication extends WebApplication implements ApplicationContextAware {
        @Override
        protected void init() {
            addComponentInstantiationListener(new SpringComponentInjector(this, ctx, true));
        }
    
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.ctx = applicationContext;
        }
    }
    

    For additional clarification of how MyWebApplication now relates to both Wicket and Spring framework here is an according class diagram:

    MyWebApplication class diagram

    MyWebApplication Class Diagram

    And that’s all folks! No additional modifications are required to the test itself. It’s gonna turn green now. This way you can use exactly the same Spring context configuration that you’d use in your runtime environment for running your JUnit based integration tests as well. Just grab the colleague you like most and try a pair programming and test first approach with Wicket and Spring. You’ll be delighted! And if you’re not, go buy yourself one of these ;) .

     
  • comsysto 14:48 on 7 May, 2010 Permalink | Reply
    Tags: , Apache Wicket, JEE, Web Application, Web Frontend   

    Apache Wicket Training von comSysto und JWeekend 

    Am 22. und 23. Mai 2010 organisiert die comSysto GmbH in Zusammenarbeit mit JWeekend und Wicket London User Group das erste Apache Wicket Training im deutschsprachigen Raum.

    Die Vermittlung der Inhalte wird an praktischen Beispielen vollzogen, so dass nach 2 Tagen eine beeindruckende, von den Teilnehmern geminsam entwicklete webbasierte Anwendung entstehen wird.

    In der Halbzeitpause des Trainings am Samstag Abend widmen wir uns noch einem sehr wichtigen Thema – Fußball! Im Champions League Finale zwischen Bayern München und Inter Mailand werden wir selbstverständlich die Bayern auf ihrem Weg zum diesjährigen “Triple” lautstark unterstützen.

    Mehr Informationen über die Ziele und Ablauf des Trainings finden Sie in unserem Flyer unter:

    comSysto Apache Wicket Training

    Bei Interesse bitte eine kurze Email an kontakt[at]comsysto.com schreiben, es sind nur noch wenige Plätze frei.

     
  • Tomislav Zorc 15:35 on 26 April, 2010 Permalink | Reply
    Tags: , QlikView, Kostenrechnung, Erlösrechnung, Reporting, Datenintegration, Controlling   

    Einfache Kosten- und Erlösrechnung mit QlikView 

    Ausgangspunkt und fachliche Anforderungen

    Ein kleineres Dienstleistungsunternehmen möchte eine einfache Kosten- und Erlösrechnung einführen. Kosten- und Erlösdaten sollen aus der DATEV-Buchhaltung übernommen werden. Eine matrix-ähnliche Organisation des Unternehmens in Teams und Projekte erforderte die zweidimensionale Betrachtung der Erlöse und Kosten. Jede Buchung wird gleichzeitig immer einer Kostenstelle (Team) und einem Kostenträger (Projekt) zugeordnet. Dafür stellt DATEV standardmäßig zwei vordefinierte Felder mit relativ unspektakulären Namen zur Verfügung: Kost1 und Kost2. Die Buchhaltung des Unternehmens sorgt dafür, dass Kost1 mit Kostenstelleninformation und Kost2 mit Kostenträgerinformation befüllt wird.

    (Team = Kostenstelle = Kost1, Projekt = Kostenträger = Kost2)

    Die dritte Betrachtungsebene sind Kostenarten, die sich aus dem originären Kontenplan ergeben und für die nur eine den Kundenanforderungen entsprechende Zusammenfassung zu Kostenarten gefunden werden musste. In einem Dinstleistungsunternehmen stellen Personalkosten einen größten Block da, so dass in der ersten Ebene zwischen Personal- und übrigen Kosten unterschieden wird. Bei übrigen Kosten wird eine weitere Unterscheidung in Reisekosten, Werbungskosten, Materialkosten usw. getroffen.

    Implementierung

    Nach genauerer Analyse einiger von DATEV angebotenen Controlling-Tools fiel die “Make-Or-Buy”-Entscheidung eindeutig auf “Make”. DATEV-Buchhaltung ermöglicht nämlich den Export von Primanota in eine semikolon-separierte Textdatei “Primanota.txt”. Die Quelle für die Fakt-Tabelle war also geboren…

    Weitere Quellen sollen nur Stammdaten (Dimensionen und evtl. Hierarchien) zu Kostenstellen, Kostenträgern und Kostenarten halten. Aufgrund sehr weiter Verbreitung bietet sich MS Excel für die Speicherung und manuelle Datenpflege durch Buchhaltung hervorragend an.

    Nach der Klärung aller Reporting-Anforderungen und Definition der Quellen konnte man mit der Implementierung anfangen, die sich grob in 2 Teilbereiche gliedern lässt:

    1. Dateinintegration

    Für die Datenintegration bietet QlikView eine SQL-ähnliche Skriptsprache mit einer großen Fülle an Funktionen zur Datentransformation und -aggregation. Nahezu jede beliebige Datenbank oder jedes beliebige Dateiformal lässt sich als Quelle hinzufügen und einheitlich mit anderen Quellen verbinden.

    Das Ergebnis des Skripts ist ein einheitliches logisches Datenmodell, das Abfragen über alle vorhandene Spalten bzw. Attribute zulässt. Somit entsteht ein logisch zusammenhängender Themenbereich, was in diesem Beispiel aus einer Fakt-Tabelle und 3 (Mini-)Dimensions-Tabellen besteht. In der Fakt-Tabelle “Primanota” haben wir neben den originären auch abgeleitete Kennzahlen und Merkmale durch Verwendung von Transformationsfunktionen definiert. Die Beziehungen zwischen den einzelnen Quellen stellt QlikView anhand der Spaltennamen fest, so dass man von Anfang an gezwungen ist, absolut saubere Namenskonventionen einzuführen.

    Bei der Ausführung des Skriptes werden alle Quellen komprimiert (Faktor 10 – 20!) und in den Arbeitsspeicher des Rechners geladen, was eine fast unglaubliche Abfrageperformance zulässt.

    2. Reporting

    Basierend auf den im ersten Schritt definierten Merkmalen und Kennzahlen innerhalb des Themenbereich lassen sich nun Berichte in allen denkbaren Darstellungsformen aufbauen – Tabellen, Pivottabellen, einfachere Linien- oder Balken- oder komplexe Radardiagramme. Zusätzlich bietet QlikView auch einige Objekte wie Schaltflächen oder Dateineingaben, die für einen hohen Grad an Benutzerinteraktion sorgen können. Wem das Ganze immer noch nicht ausreichen sollte, hat er die Möglichkeit per VBScript oder JScript die Kontrolle selbst zu übernehmen.

    Eine Auftelung der erstellten Tabellen, Diagramme und sonstiger Objekte auf einzelne Dashboards bzw. Seiten (in unserem Beispiel “Reports” und “Details”) ermöglicht eine klare Struktur und bessere Navigation.

    Weitere nette Möglichkeit ist die “Ein-Klick” Umstellung einer Anzeige (z.B. Tabelle) in eine andere Anzeige (z.B. Balkendiagramm). Nachfolgend sieht man ein Balkendiagramm, der durch einen Klick aus der Tabelle “Monatsübersicht” entstanden ist.

    Aufgrund der Tatsache, dass QlikView alle Daten im Arbeitsspeicher hält, ergibt sich auch eine sehr schnelle und von anderen BI-Werkzeugen in der Form nicht bekannte Möglichkeit der assoziativen Analyse. Durch die Auswahl eines Wertes aus einer Spalte werden alle assoziierten Werte in anderen Spalten weiß hinterlegt, die nicht-assoziierten Werte werden ausgegraut. Unter “Current Selections” sieht man auf einen Blick jede getroffene Auswahl.

    Assoziative Analyse mit QlikView eignet sich hervorragend für die Suche nach Datenqualitätsproblemen, eine einfache Erkennung von Mustern in den Rohdaten oder für komplexe Filterbedingungen. In unserem Beispiel verwenden wir die assoziative Analyse durch die Anzeige des Buchungskommentars für eine einfache Übersicht aller einzelnen Buchungen, die sich hinter einer Kosten- bzw. Erlössumme verstecken.

    Fazit

    Mit QlikView ist es uns gelungen innerhalb weniger Tage eine zwar einfache aber den Anforderungen völlig entsprechende Kosten- und Erlösrechnung für das kleine Dienstleistungsunternehmen aufzubauen. Schnelle Datenintegration ohne zusätzlichen Aufbau von relationalen Datenstrukuren in Form eines DWH basiert zwar auf SQL-ähnlichen Skripten und setzt einen bestimmten SQL-Kenntnisstand voraus, doch das Ganze wird durch einige Wizards entschärft, die aus den getroffenen Einstellungen den Skriptcode automatisch produzieren.

    Im Reporting-Bereich lässt QlikView durch sehr intuitive Bedienung und viele Darstellungsmöglichkeiten keine Wünsche übrig. Erweiterung der Standardfunktionen durch VBScript oder JScript ist zwar möglich, sollte aber selten notwendig sein. Ein absolutes Alleinstellungsmerkmal ist die schon beschriebene assoziative Analyse und die “In-Memory” Datenverarbeitung mit Datenkompression, die für exzellente Performance auch mit großen Datenmengen sorgt.

    Im Rahmen unseres Projektes wurde QlikView Personal Edition benutzt – ein Softwarepaket, das gänzlich auf dem Desktop-Rechner zu installieren ist. Für große Unternehmen mit vielen Anwendern kommt die Server Edition mit klassischer Client-Server-Architektur in Frage. Zusätzlich bietet QlikView einen sehr bequemen web-basierten sowie zwei mobile (iPhone und Android) Clients zur Verfügung.

     
  • Tomislav Zorc 12:04 on 5 January, 2010 Permalink | Reply
    Tags: comsysto, nature resort, offsite meeting, open world, rafting, tirol   

    comSysto Offsite Meeting and white-water Rafting in Oetz, Tirol 

    I wanted to use the opportunity of writing my first post on our corporate blog about something absolutely not related to technology, CRM, business, SCRUM,  JEE, Intelligence or whatever “usual” topic you have read and will read here.  It should be some kind of smooth start for my blogging career…

    Here is what I want to share with you – my impressions of our offsite meeting in Tirol, Austria on 26. and 27.9.2009. It was a get together for all “comSystos”, regardless of their role, position, education, business and technological background, sex, nationality, hair or skin colour. More ambitious people like Maxim would even call it “comSysto Open World”, I want to stick to something simpler like offsite meeting or get together.

    We planned it as a work-fun weekend in a relaxed atmosphere and magnificent Tirol mountain and river scenery. And that’s the way it started on Saturday. We arrived to “Nature Resort” in Oetz and had our lunch with Tirol specialties on the terrace enjoying the late summer sun and glorious Tirol mountains. The work part began in the afternoon with the goal to share thoughts, informations, ideas and impressions around comSysto – projects, clients, people, planning, tools, processes, financials, strategy, goals, objectives, … Seems like it was interesting since our guides who were supposed to show us the way to the restaurant waited more than 40 minutes until everybody showed up.

    Quite late and even more hungry we started our walk to the restaurant following a trekking route through Tirol forrest. After 45 minutes and right before it got very dark we arrived to a lonely small restaurant located next to a nice mountain lake. Extremely friendly Tirol people served good food, loads of beers and home-made liquor while singing some for us not understandable and probably traditional Tirol songs. Few hours later our way back to “Nature Resort” was leading us through complete darkness, which can be experienced only in wild nature or at deep sea. Our guides had a solution once again – one real old-fashioned torch for everyone since fire is not only providing light but also keeping wild animals off! The biggest challenge was to hold the torch properly and not to burn yourself or people next to you, which is no surprise given the amount of beers and “schnapps” for dinner. Once we finally reached the resort with no losses or injuries, few of us decided to have some more drinks while the rest was smart enough and went straight to bed.

    While the smart rest was having a breakfast Sunday morning, few of us were slowly waking up and trying to fight the hangover. We had to hurry since our guides were waiting again. The fun part of our weekend was straight ahead – rafting on the Inn river! Inn has its source in a “gletscher” near St. Moritz (Switzerland). It ends in Passau (Germany) joining famous Danube. Several other smaller streams also coming down from icy and snowy mountain tops join Inn when it’s passing Tirol (Austria). A fact that Inn’s water temperature even in hottest summers hardly exceeds 7° C is not a surprise but we didn’t think about it before.

    After pressing ourselves into neoprene suites and feeling literally like “presswurst”, we had to prove our guides that everybody is smart enough to row. Sounds silly, but half an hour later I was sorry we didn’t excercise more. Dry rowing finished and we had to get wet.  Probably not less than 5° C (it felt like -25°) did the rest to our hangover – even in neoprene.

    We were split into 4 groups on 4 boats, 2 bigger ones for 6-8 people and 2 smaller ones for 4 people. Getting into the boats and starting in slow water was easy. First white waters were managed easily and we got carefree. Our route on the Inn is rated with rafting severity degree of 3 – 4. Then it happened – a white water spot not much worse than the ones before turned our boat upside-down. The guide was shouting “row, row”, some of us thought they were doing it, some of us already panicked and didn’t do it. The result was a “flip” our guide called “nice”, 1 pair of glasses lost, 1 pair of sunglasses (playing cool when rafting!) lost and 4 guys swimming around in panic. We managed to get into our boat again after a while and were completely frozen. But after all it was a good thing – we took rafting, our guide and his commands more seriously and everything went well.

    At the total of approx. 1,5 hours our rafting ended when we reached the final stop where showers, dry clothes, food, drinks and our cars were waiting for us. Few Tirol sausages, beer, Almdudler and afternoon sun helped us recover and start our 2 hours drive back to Munich.

    Ötz, “Nature Resort”, many thanks, everything was perfect, we’ll be back! But next time we will raft on “Ötztaler Achen” (severity 5 – 6) ;-) Meanwhile we’ll try some sailing!

     
  • DamirAbdic 18:01 on 27 November, 2009 Permalink | Reply
    Tags: action script, adobe, catalyst, flash, flex   

    Adobe Flash Catalyst: Testbeispiel 

    Adobe Flash Catalyst

    Ein sehr gutes Einstiegsbeispiel für Adobe Flash Catalyst:

    http://createordie.de/cod/artikel/Flash-Catalyst-2575.html

    Nachdem man das Beispiel durchgespielt hat, versteht man auch warum die vielversprechende Software es noch nicht in die Ladenregale geschafft hat. Das Setzen der Eigenschaften der Komponenten funktionert noch nicht.

    Gelangt man zum letzten Schritt, bei dem man “setProperty” setzen möchte um das mittlere Bild bei den Transitions vom 1. bis zum 3. Bild und umgehehrt auszublenden, stellt man fest dass eine BETA Software eben mal Mängel hat. Durch Klicken auf “Add Action” legt man zwar eine Aktion an, aber dann kann man die Properties im Property-Reiter nicht bearbeiten. Dieses Problem lässt sich durch folgende Code-Modifizierung (z.B. im Flash Builder) beheben.

    Adding an instance of the Fade Class

    Innerhalb der Transitions:  fromState=”Page3″ toState=”Page1″ und fromState=”Page1″ toState=”Page3″ fügt man noch eine Instanz der “Parallel  – Klasse” ein. Durch den Fade – Effekt kann man beispielsweise das mittlere Bild transparent schalten. Das “autoReverse” property macht dies rückgängig, sobald man zu einem anderen “State” wechselt.

     
  • MaximDemenko 23:52 on 25 August, 2009 Permalink | Reply  

    Oracle BI with multiple Repositories and MySQL Datasource 

    Probably well known fact is that Oracle BI server can serve multiple repositories at the same time.  Equally well known is that MySQL (or any ODBC source) can be accessed by Oracle BI. At least theoretically.  In fact, it works, but there are some pitfalls, which one should be aware of. Ok, it sounds a little unrelated to each other and one can ask – why bother, in most cases it is still Oracle, oc4j and only one instance per machine.  Right. The problem with this standard configuration (of course, it is only my personal opinion) – it is delivered and works out of the box.  It is not bad at all, but most part of configuration is done in background and the person who implement oracle bi doesn’t get a chance to understand configuration in such default environment.  Chosing nonstandard components ( and it is often a requirement in a custom project) provides better understanding how single components work together.

    OBIEE Architecture

    OBIEE Architecture

    In general it isn’t at all the most terrible idea to have a look into documentation and try to understand architecture of the software product before start to install or configure it.  From the picture (borrowed from the oracle documentation) it is clear that the 3 components (marked red on the picture) are the most important in this architecture:

    • j2ee server (web application containter) which communicates with presentation services and brings the data to the client (web browser)
    • presentation services which communicates with web tier and with oracle bi server (over odbc)
    • oracle bi server which performs the actual bi queries and communicate with data source (rdbms or odbc source or xml file)

    To serve multiple repositories only one instance of bi server is needed, corresponding rpd files should be placed into OracleBI_HOME/server/Repository directory:

    tree  ../server/Repository/ -P "*.rpd"
    ../server/Repository/
    |-- paint.rpd
    |-- sakila.rpd
    |-- samplesales.rpd
    `-- sh.rpd
    

    and every repository should be referenced in oracle bi config file (NQSConfig.INI):

    [ REPOSITORY ]
    
    // Star = samplesales.rpd, DEFAULT;
    samplesales = samplesales.rpd, DEFAULT;
    sh = sh.rpd;
    sakila = sakila.rpd;
    

    That’s all regarding bi server, for presentation service a little bit more work is required, but first i would like to show how MySQL database and odbc DSN should be configured (because the blog title implies, not only multiple repositories, but one of them with MySQL as datasource). To create a database (please, don’t blame me for absolutely no security consideration, it’s only an example) – install mysql with any suitable tool – for example with yum. My test system is Cent OS 5.3 x86-64 machine, on the RHEL or OEL setup is absolutely the same, 32bit platform don’t differ much ( but there are some differences, which i’ll  mention later). After that, assuming mysql is started:

     mysql -u root
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 59
    Server version: 5.0.45 Source distribution
    Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
    mysql> create database sakila;
    Query OK, 1 row affected (0.02 sec)
    mysql> grant all privileges on sakila.* to biee@'localhost' identified by 'biee' with  grant option;
    Query OK, 0 rows affected (0.00 sec)
    mysql> grant all privileges on sakila.* to biee@'%' identified by 'biee' with grant option;
    Query OK, 0 rows affected (0.01 sec)
    mysql> flush privileges;
    Query OK, 0 rows affected (0.00 sec)
    mysql> Bye
    mysql -u root sakila < sakila-schema.sql
    mysql -u root sakila < sakila-data.sql
    

    The demo database sakila can be downloaded from MySQL documentation page. Next step is to configure and test an odbc connection for this datasource. To do that, add to the system odbc config file ( /etc/odbc.ini) following section:

    [sakila]
    Driver       = /usr/lib64/libmyodbc3.so
    Description  = Connector/ODBC 3.51 Driver DSN
    SERVER       = localhost
    PORT         = 3306
    USER         =
    Password     =
    Database     = sakila
    OPTION       =
    SOCKET       = /var/lib/mysql/mysql.sock
    

    and test the connection with the ODBC client isql

    isql sakila biee biee
    +---------------------------------------+
    | Connected!                            |
    |                                       |
    | sql-statement                         |
    | help [tablename]                      |
    | quit                                  |
    |                                       |
    +---------------------------------------+
    SQL> select table_name,engine FROM information_schema.tables where table_schema='sakila';
    +-----------------------------------------------------------------+-----------------------------------------------------------------+
    | table_name                                                      | engine                                                          |
    +-----------------------------------------------------------------+-----------------------------------------------------------------+
    | actor                                                           | InnoDB                                                          |
    | actor_info                                                      |                                                                 |
    | address                                                         | InnoDB                                                          |
    | category                                                        | InnoDB                                                          |
    | city                                                            | InnoDB                                                          |
    | country                                                         | InnoDB                                                          |
    | customer                                                        | InnoDB                                                          |
    | customer_list                                                   |                                                                 |
    | film                                                            | InnoDB                                                          |
    | film_actor                                                      | InnoDB                                                          |
    | film_category                                                   | InnoDB                                                          |
    | film_list                                                       |                                                                 |
    | film_text                                                       | MyISAM                                                          |
    | inventory                                                       | InnoDB                                                          |
    | language                                                        | InnoDB                                                          |
    | nicer_but_slower_film_list                                      |                                                                 |
    | payment                                                         | InnoDB                                                          |
    | rental                                                          | InnoDB                                                          |
    | sales_by_film_category                                          |                                                                 |
    | sales_by_store                                                  |                                                                 |
    | staff                                                           | InnoDB                                                          |
    | staff_list                                                      |                                                                 |
    | store                                                           | InnoDB                                                          |
    +-----------------------------------------------------------------+-----------------------------------------------------------------+
    SQLRowCount returns 23
    23 rows fetched
    SQL> quit
    

    For odbc connections oracle bi uses its own odbc. ini , which is located in OracleBI_HOME/setup/odbc.ini. After being ensured odbc connection works, the simplest step is to copy the odbc.ini entry for this database. Indeed, it is enough on 32bit platform, but doesn’t work on x86-64 – oracle bi couldn’t connect to my database. For troubleshouting, the usual suspicious were very useful (as expected):

    • bi server log (Oracle_BI_HOME/Log/NQServer.log)
    • odbc trace file (activated by following section in oracle bi  odbc.ini file)
    • [ODBC]
      # Trace=0
      Trace=1
      TraceFile=/tmp/odbctrace.out
      TraceDll=/opt/biee/OracleBI/odbc/lib/odbctrac.so
      InstallDir=/opt/biee/OracleBI/odbc
      UseCursorLib=0
      IANAAppCodePage=4
      
    • system calls trace ( strace -f -o /tmp/nqsserver.trc -p process_id_of_bi_server)

    In short, the issue is:  oracle bi on linux exists only as 32 bit software. That is not a problem to run it on x64 bit system, oracle software itself works fine. But supplied odbc driver manager ( from data direct) is in 32bit version as well ( probably 32bit nqsserver can only be accessed over 32bit odbc driver) and it’s unable to load 64bit linux library for mysql odbc driver. Well, but it should be possible to access 64bit database with 32bit odbc client – was my first thought. Indeed, it works, but odbc driver in 32bit version  doesn’t exist for x64 CentOS ( and i assume – RHEL and OEL ) distribution. I don’t think, it’s a bug, in opposite, i tend to assume – there are some conflicts in running 32bit odbc client on 64bit system, however, i could not find any issue in internet or on my test system – and workaround is rather simple – download odbc driver from 32bit repository and use it for bi server. This don’t work out of the box – bi server driver manager can not load 32bit driver as well – but for another reason – it can’t find 32 bit mysql client libraries. Simple to solve – just extend LD_LIBRARY_PATH  appropriated (the same is very true regarding Oracle client on a 64bit Linux – oracle bi has to be pointed to 32bit libraries as well) , here is the final configuration for biee os user (first one for environment and second for OracleBI_HOME/setup/odbc.ini) :

    echo $LD_LIBRARY_PATH
    /opt/oracle/product/10.2.0.4/lib32:/usr/lib:/lib:/usr/lib/mysql:/usr/lib:
    
    [sakila]
    Driver = /usr/lib/libmyodbc3.so
    DATABASE = sakila
    DESCRIPTION = sakila
    USER =
    PWD =
    PORT = 3306
    SERVER = localhost
    SOCKET = /var/lib/mysql/mysql.sock
    
    [AnalyticsWeb01]
    Driver=/opt/biee/OracleBI/server/Bin/libnqsodbc.so
    Description=Oracle BI Server
    ServerMachine=local
    Repository=samplesales
    Catalog=
    UID=
    PWD=
    Port=9703
    
    [AnalyticsWeb02]
    Driver=/opt/biee/OracleBI/server/Bin/libnqsodbc.so
    Description=Oracle BI Server
    ServerMachine=local
    Repository=sh
    Catalog=
    UID=
    PWD=
    Port=9703
    
    [AnalyticsWeb03]
    Driver=/opt/biee/OracleBI/server/Bin/libnqsodbc.so
    Description=Oracle BI Server
    ServerMachine=local
    Repository=sakila
    Catalog=
    UID=
    PWD=
    Port=9703
    

    The first DSN will be used by bi server itself to connect to datasource, the other 3 – by presentation services to connect to bi server.  It means, while bi server can serve 3 different repositories, at the same time, 3 instances of presentation services are needed (separate instance for each repository). All of them connect to the bi server on the port 9703 and to distinguish different repositories they use different DSN’s. They need as well a listening address ( to enable communication with web tier) and it should be different for each instance of course. To implement it – 3 different configuration files are required ( instead of  instanceconfig.xml in OracleBIData_HOME/web/config ) , which can be created as copies of instanceconfig.xml) . Default configuration uses 9710 as listening port, so, a smart idea could be to use 9711 ans 9712 for additional config files. For example, the relevant (changed)  section from instanceconfig02.xml and instanceconfig03.xml looks like:

    <WebConfig>
     <ServerInstance>
     <DSN>AnalyticsWeb02</DSN>
     <Listener port="9711" />
    <CatalogPath>/opt/biee/OracleBIData/web/catalog/sh</CatalogPath>
    
    <WebConfig>
     <ServerInstance>
     <DSN>AnalyticsWeb03</DSN>
     <Listener port="9712" />
    <CatalogPath>/opt/biee/OracleBIData/web/catalog/sakila</CatalogPath>
    

    After that – 3 instances of presentation services can be started (the sawserver executables accept a -c commandline parameter to specify a configuration file). Unfortunately, delivered run-saw.sh doesn’t allow to start multiple instances, so i wrote a customized start script (i apologize for inconvinient media type – but the script is too long to post it here and i am really newby in regard to wordpress , i.e. i didn’t found a way to upload a shell script, that’s why i chose a pdf) , which does the same as supplied script, but additionally

    • allows start a single instance with specified config file ( either full path to instanceconfig.xml or only basename)
    • allows stop of a single instance with specified config file
    • checks existence of specified config file
    • takes care to write to separate log file for each instance
    • takes care to not start a javahost server only by startup of first instance presentation services and shut down only if the last instance is shutdown

    I consider it as dirty hack, although, it works fine for me on Linux – but probably, there are some bugs , additionally i didn’t test it on solaris or hpux – so, please test it carefully if you decide to use it.  After all, the typical use case for it looks like:

    ./run-config-saw.sh -c instanceconfig02.xml start
    Oracle BI Presentation Services with process id 27097 and config instanceconfig02.xml is already running.
    Oracle BI Java Host with process id 26428 is already running
    ./run-config-saw.sh -c instanceconfig02.xml stop
    Stopping Oracle BI Presentation Services with process id 27097 and config instanceconfig02.xml
    ./run-config-saw.sh -c instanceconfig02.xml start
    Starting Oracle BI Presentation Services with config file instanceconfig02.xml
    Oracle BI Presentation Services startup initiated.
    ./run-config-saw.sh -c whateveryoutypewrong start
    Config File /opt/biee/OracleBIData/web/config/whateveryoutypewrong doesn't exist
    Exit now ...
    

    Now, after bi server and presentation services are configured, the last tier – webserver deployment should be completed. In my setup i used WebLogic (i consider myself slightly biased in regard to it – i like, how this software is designed and implemented), but the process is very similar on JBoss, Tomcat,OC4J or whatever you choose. To deploy the analytics.war under bea as 3 different applications – simply create 3 different directories under chosen deployment directory ( could be anywhere in system), extract analytics.war archive in each of them and modify web.xml configuration file to reflect the listening port of presentation services.

    cd /opt/biee/Middleware
    mkdir deployments
    cd deployments
    mkdir analytics0{1,2,3}
    for dir in analytics*
    do
     (cd $dir;jar -xf /opt/biee/OracleBI/web/analytics.war)
    done
    

    After modifiing web.xml for each application, it looks like

     cat analytics0{1..3}/WEB-INF/web.xml|grep -C 3 oracle.bi.presentation.sawserver.Port
    <param-value>localhost</param-value>
     </init-param>
     <init-param>
    <param-name>oracle.bi.presentation.sawserver.Port</param-name>
    <param-value>9710</param-value>
     </init-param>
     </servlet>
    --
    <param-value>localhost</param-value>
     </init-param>
     <init-param>
    <param-name>oracle.bi.presentation.sawserver.Port</param-name>
    <param-value>9711</param-value>
     </init-param>
     </servlet>
    --
    <param-value>localhost</param-value>
     </init-param>
     <init-param>
    <param-name>oracle.bi.presentation.sawserver.Port</param-name>
    <param-value>9712</param-value>
     </init-param>
     </servlet>
    

    The last step is to go to WebLogic Admin console and deploy these web applications ( it can be done with wlst as well)  – some screenshots  follows

    After deployment it should be possible to access every single Oracle BI presentation service under its url (i configured WebLogic server to listen on Port 7003 – like in my previous blog post) :

    Last thing to be mentioned – the configuration with multiple presentation services on the same host is not officially supported by oracle. But for development purposes it may be fully acceptable  – as long as it works.

    Deployment Step 1

    Deployment Step 1

    Deployment Step 2

    Deployment Step 2

    Deployment Step 3

    Deployment Step 3

    Deployment Step 4

    Deployment Step 4

    Deployment Step 5

    Deployment Step 5

    Deployment Step 6

    Deployment Step 6

     
    • rnm1978 10:45 on 10 September, 2009 Permalink | Reply

      Excellent post, and interesting comments around getting ODBC 32/64 bit working.

      • MaximDemenko 09:02 on 11 September, 2009 Permalink | Reply

        Thank you for kind words

    • Calista Gelbach 06:05 on 19 March, 2010 Permalink | Reply

      Ich hab darueber erst mal wo gelesen, extrem gutes Thema. Ich komme wieder.

c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
esc
cancel