careers.comsysto.com goes live!

careers.comsysto.com ist die neue Karrierewebseite der comSysto GmbH! Mit dem Launch der Karrierewebsite intensiviert die comSysto GmbH ihre Suche nach motiviertem, hochqualifizierem Fachpersonal in den Bereichen JEE, Business Intelligence und Oracle Datenbank Administration.

Die neue Karriereseite richtet sich an Studenten, Absolventen und Professionals, die daran interessiert sind, ihren beruflichen Erfolg in einem stabil wachsenden Unternehmen weiter zu entwickeln und Teil eines starken Teams zu werden. Neben allgemeinen Informationen zu Kompetenzen und angewandten Technologien, den Kunden und Branchen, in denen die comSysto GmbH tätig ist, sowie der Unternehmenskultur, werden auf careers.comsysto.com regelmäßig offene Positionen im Unternehmen veröffentlicht. Hier sind eine Beschreibung der Positionen, sowie die fachlichen und persönlichen Anforderungen an den Bewerber zu finden. Als ein individuell fördernder und mit zahlreichen, ergänzenden Leistungen das Engagement belohnender Arbeitgeber, finden sich auf der Website zudem eingehend beschriebene Informationen zu den Benefits, die die Chancen und Perspektiven des Mitarbeiters bei comSysto unterstreichen. Einen ersten Einblick in die Vielfalt des Teams, in ihre fachlichen Kenntnisse und Fähigkeiten, sowie in Unterhaltsames aus dem Nähkästchen, erhält man ebenfalls auf der neuen Karrierewebsite.

ComSysto wird MongoDB Spezialist

Um das exzellente Fachwissen der comSysto-Mitarbeiter im Bezug auf NoSQL-Datenbanken zu vervollständigen, fand am 28. und 29. Juni eine MongoDB-Schulung statt. Wie bereits schon bei der Wicket-Schuleung durch jWeekend hat comSysto auch dieses mal weder Kosten noch Mühen gescheut um einen ausgezeichneten Experten im Bezug auf MongoDB nach München zu holen. Sein Name ist Brandan McAdams, er arbeitet für 10gen, die Firma hinter MongoDB. Brandan ist nicht nur Entwickler von MongoDB (v.a. Treiber), sondern hat auch viel praktische Erfahrung aus dem Consulting-Bereich. Außerdem merkt man ihm an, dass ihm das Schulungen halten wohl sehr Spass macht. Weiterhin hat Brandan einen Sinn für gutes Bier, so dass er sich in München richtig wohl gefühlt hat (Augustiner Dunkel, excellent choice).

NoSQL-Datenbanken erfreuen sich seit einiger Zeit immer mehr Beliebtheit und es sind in den letzten Jahren einige sehr interessante Produkte wie MongoDB, CouchDB, Cassandra und viele mehr entstanden. Nicht zu vernachlässigen sind die Entwicklungen von Google (BigTable) und Amazon (SimpleDB). Neu ist diese Form der Datenbanken allerdings nicht, denn schon die BerkeleyDB, die z.B. von Subversion eingesetzt wird, zählt zu diese Form von Datenbanken. Bisher wurden Datenbanken dieser Art in eher technischen Anwendungsbereichen eingesetzt, wie z.B. memcached zum Clustern von Sitzungen verschiedener Applikationsserver.

Nicht jede NoSQL-Datenbank kann für jeden Zweck gebraucht werden und NoSQL-Datenbanken sind bestimmt nicht das Allheilmittel für alle Problemstellungen. Man muss sich also vor der Entscheidung, welche Datenbank man einsetzt, genau mit den Anforderungen auseinander setzen. Um einen ersten Anhaltspunkt zu bekommen, kann man NoSQL-Datenbanken in verschiedene Kategorien einteilen. Die geläufigsten sind:

  • Key-Value-Store (memcached)
  • Dokumentenorientiert (CouchDB, MongoDB)
  • Tabellenorientiert (BigTable)

Der Einsatz von NoSQL-Datenbanken findet oft dort statt, wo auf eine sehr große Anzahl von komplex strukturierten Daten zugegriffen werden muss und Eigenschaften wie Performance, Verteilbarkeit und Ausfallsicherheit wichtiger sind als Datenkonsistenz. Nach dem CAP-Theorem1 kann ein System nicht gleichzeitig diese drei Eigenschaften erfüllen:

  • Konsistenz
  • Verfügbarkeit
  • Partitionstoleranz

Dem entsprechend gibt es in MongoDB keine Transaktionen, also auch kein ACID-Prinzip. Es können jedoch bestimmte Anpassungen gemacht werden, damit Daten zu einer bestimmten Anzahl von Knoten geschrieben werden müssen um sichtbar zu sein.

Obwohl die Schulung zwar nur zwei Tage dauerte, schaffte es Brandan die comSysto-Mitarbeiter in die meisten Facetten der MongoDB einzuweihen. Unter anderem wurde behandelt:

  • Installation
  • CRUD
  • Suchen
  • Gruppieren, MapReduce
  • Indizierung, Performanzmessung und Optimierung
  • Schemadesign
  • Anbindung von Anwendungsprogrammen in Java Javascript und PHP an die MongoDB
  • Betrieb, Replikation, Sharding, Backups

ComSysto freut sich, MongoDB als sehr vielversprechende Technologie in sein Portfolio mit aufzunehmen und die Expertise der Mitarbeiter ständig zu verbessern. Dies wird u.a. auch dadurch gewährleistet, dass comSysto die neue MongoDB User Group ins Leben gerufen hat. Die Mitarbeiter freuen sich, viele interessante Vorträge über MongoDB und verwandte Themen zu hören und zu halten. Nähere Infos zur MongoDB User Group finden sich hier.

Aus unserer Sicht war die Schulung ein voller Erfolg und wir sind guter Dinge, MongoDB in unseren Projekten noch besser einzusetzen um den maximalen Benefit für unsere Kunden zu gewährleisten.

Why choose Apache Wicket?

Initially I just can say: Wicket is the best web framework I have ever used. Meanwhile I have successfully finalized my third project with it. In the following few lines I will try to list the arguments for using wicket from both business and technical point of view, but the most important one is actually that each of those projects has been a success story at the end.

Business aspects

Open-Source and free

Apache Wicket is free. There are no license costs and you are not bound to a ‘one and only’ company for support. If you are having trouble with a consulting company you work with, simply go and find a better supporter. Before Wicket we used a commercial Struts-like framework and we were not allowed to get the source code of the framework in question so we had to debug and search for bugs without it. It took weeks before we got our support requests answered and even months before we got the bugfixes delivered for that framework.

Fast development turnaround safes time and money

The development turnaround is very fast. One of our customers told us, since we switched to Apache Wicket the velocity is three times faster than before (measured with scrum tools).

Wide-spread knowledge

Wicket provides a big community which reacts on bugs and questions quickly. Knowledge about that framework is wide-spread and not just centralized in one company. What if the company which provides a closed-source web-framework go bust? You are dependent on that company. Furthermore the documentation and examples of Wicket usage are increasing. In contrast the commercial framework we used: the documentation was bad and had not evolved so that you have had to contact the support and pay for it.

Higher quality and stability

Since we use Wicket we have less bugs, a higher stability and qualtity in our software. But what Wicket cannot do is automatically write good code and correct architecture flaws. So you will need good developer with strong object orientation skills. Meanwhile you can find a lot of companies and developer which provide Wicket know-how and support, so the argument of missing development resources is not valid anymore.

Avoiding software erosion and react on requirement changes fastly

Wicket provides very good refactoring capabilities that enables you to react on requirement changes quickly. Additionally the refactoring capabilities keep the software erosion low. Often a software is already outdated on its first launch, because the requirements have often changed. Most web frameworks does not provide good refactoring capabilities, so that developer avoid bigger changes. After a while you often cannot understand the business logic from the source code anymore, but you should. So the software is already outdated and software erosion has taken control over.

Developer acceptance

In my experience Wicket has high acceptance by developer and motivated developer are more productive. Thanks to testabilty you can detect bugs early. There is a high reuse of existing frontend parts and aspects through components. Ideally you can create a component catalog, where the business department picks the components from and build there websites with it.

Technical aspects

Less technologies

There are just two technologies: Java and XHTML. This makes it easy to learn Wicket, you do not have to learn new templating engines. You just bind your components to the XHTML through an own Wicket namespace. Everything can be bundled in a jar file and these can be bundled within war files. Less technologies causes less failure points. The only failure points are the binding between the java component and its matching HTML and the property paths of the PropertyModel. These possible failures can be completely reduced with unit tests though.

Pure object-orientation

This is an advantage and disadvantage. A lot of developer are not able to develop object-oriented. Most people learn to use the power of object-orientation with Wicket. They have been developing Java for years, but they developed procedural mostly. What are services? Procedural. What are controllers in Struts? Procedural. What are beans? Just value holders. There is no real object-orientation. Wicket changes that, so the challenge is not to learn Wicket, but rather learn object-orientation. Object-orientation makes it easy to develop and cut clear business aspects.

Separation between layout and logic / JSP-free

Wicket uses pure XHTML which is XML. You have a clean HTML template with Wicket’s own namespace, so that you can bind the Wicket components to it. JSPs are bad. They are not compile-save, often confusing, usually containing a lot of business logic and they are not testable. At least you cannot bundle them into jar-files. In Wicket all the logic is in Java-code which makes it compile-save, unit testable and debugable. The raw HTML-Template makes it easy for a web designer to customize layout. So you can easier split the work between web designer and developer. Normally developer are more expensive than web designer and the developer should not waste his/her time with doing layout. Nevertheless both need to communicate with each other to integrate a layout appropriately.

Refactoring capabilities / Keep the business logic up-to-date

Refactoring is a major issue in development. It is always needed when requirements are changed and this happens very often. Frameworks like Struts use JSPs and other technologies which are not compile save. This makes a refactoring very hard, risky and sometimes impossible. So the developer hacks the changes into the existing skeleton. That causes an unclear and unmaintable code. Often the code is already outdated and fragmented before the first launch. As I explained above, Wicket just uses Java and XHTML. Due to its focus on Java it is possible to refactor code easily with existing tools like Eclipse. You keep your application logic in sync with the business logic. The few failure points can be covered with unit tests.

No session wasting and safe flows

In classic MVC applications everything was stored in the session. After a while the session was just a global garbage – sometimes a garbage dump. The developer forget to cleanup the session and it got bigger and bigger. Nobody knows whats in it. This can cause performance and security leaks. Furthermore every value gets unsafe casted, which can cause an unstable application and more bugs.

In contrast the Wicket session is type-safe. It can be a POJO. The Wicket session is just for global information like user authentification. Wicket pages are stateful. This allows to pass information from one page to another directly. Passing information from one page to another brings a lot of advantages. The user cannot start a flow without accessing the first page. This makes a flow safe. If a user aborts the flow, the passed data gets automatically cleaned up, because information is directly bound to that concret page instance. So you can concentrate on developing flows and not on data clean up.

Components

Components are reusable. Thus saves development time and avoids duplicated code. The logic for a busniess aspect is encapsulated in a component or in some components which can interact with each other. The encapsulation causes an easier understanding of business aspects from code. Furthermore these encapsulated components are easier to test. So the business logic is not wide spread over the code like in classic MVC web applications. There is a technical separation between model, view (which often uses expression languages) and controller. These layers cause that you have to spread one business aspect over these three layers. Normally you do not have only one business aspect. Then you are mixing all business aspects within the technical separations and later you cannot detect any coherent business aspect anymore. In contrast a component does exactly represent one business aspect and this one is reusable. Components can be bundled in jar files, so it is possible to share components between different departments. In some applications I have seen the “WAR-overlay” pattern, which extracts a bundled war file to copy it in another war file. I mean a bundled war file must not be extracted, it is already bundled and should work as it is. There are new risks like wrong configuration, destroying the encoding, etc. The developer have to do that, because JSPs are not packagable in jar files. In my opinion an anti-pattern, which is provided by default in Maven. As I explained in Wicket you can bundle all your components with markup in jar files and these jar-file can be bundled in a war file without extracting. Clean packaged.

AJAX integration

Nowadays a lot of web applications must provide AJAX-features. Wicket has a built-in and easy-to-use AJAX support. It is easy extensible and usable with AJAX frameworks like JQuery.

Testability

Wicket is one of very few web frameworks which provides a testing API. So you can validate that your components and pages do render and behave correctly. For example a registration form: a user provides values for all the fields and presses the register button. You can validate that the register-service call only happens when the form was successfully filled. For validating these calls you can use a mock framework like Mockito. Even AJAX testing is possible, but this is not sophisticated enough yet. Nevertheless the WicketTester provides the best testing API I have seen yet.

Conclusion

Wicket development is fun! I realized three projects with it. It just works and has caused very few problems. I think nobody of my collegues would switch to another framework. Wicket is the most productive web framework I have ever seen.

Thanks to Daniel Bartl and Samer Al-Huanaty for correction.

Munich MongoDB User Group: First Meetup

You are invited to the First Meetup Munich MongoDB User Group!

Date: 6/28/2011
Time: Starting 7pm
Who: Brendan McAdams, 10gen Corp.
Subject: „A MongoDB Tour for the Experienced and Newbie Alike“
Location: Münchner Technologiezentrum, comSysto GmbH, Agnes-Pockels-Bogen 1, D – 80992 Munich
http://www.comsysto.com/
http://twitter.com/#!/comsysto

A Few Facts on MongoDB:
„MongoDB is an open source, document-oriented database designed with both scalability and developer agility in mind. Instead of storing your data in tables and rows as you would with a relational database, in MongoDB you store JSON-like documents with dynamic schemas. The goal of MongoDB is to bridge the gap between key-value stores (which are fast and scalable) and relational databases (which have rich functionality).
Using BSON (binary JSON), developers can easily map to modern object-oriented languages without a complicated ORM layer. This new data model simplifies coding significantly, and also improves performance by grouping relevant data together internally.
MongoDB was created by former DoubleClick Founder and CTO Dwight Merriman and former DoubleClick engineer and ShopWiki Founder and CTO Eliot Horowitz. They drew upon their experiences building large scale, high availability, robust systems to create a new kind of database. MongoDB maintains many of the great features of a relational database — like indexes and dynamic queries. But by changing the data model from relational to document-oriented, you gain many advantages, including greater agility through flexible schemas and easier horizontal scalability.“

Do you want to learn more about MongoDB? Then please register via
http://www.meetup.com/Munchen-MongoDB-User-Group/
or
https://www.xing.com/events/munich-mongodb-user-group-meetup-781984
and give us a visit! The number of participants is unfortunately limited to 50.

For any further information please contact Matija Gasparevic/office@comsysto.com/

Apache Wicket – Best Practices

Apache Wicket became very popular in the last months and has been used in many projects. Due to the power of Wicket you can develop features very easy and fast. There are many ways to realize these features though. This article provides some cook recipes for the correct, efficient and pertinent usage of Apache Wicket.

This article is addressed to developers, who has already made their first experiences with Apache Wicket. Developer, who get into Wicket often have difficulties with it, because they apply the typical JSF and Struts patterns and approaches. These frameworks primarily use procedural programming methods. In contrast Wicket is strongly based on object oriented patterns. So forget the Struts and JSF patterns, otherwise you won't have fun with Wicket in the long run.

Encapsulate components correctly

A component should be self-contained. The user of a component should neither have to know nor care about its internal structure. She should just be familiar with its external interfaces and its documentation in order to be able to use it. This means in detail: Every component that extends Wicket's own Panel type (thus is a Panel itself) must provide its own HTML template. In contrast when a component extends the classes WebMarkupContainer or Form, there is no HTML template. This implicates that you should add components through composition in WebMarkupContainer or Form.

// Poor component
public class RegistrationForm extends Form<Registration> {
    public RegistrationForm(String id, IModel<Registration> regModel) {
        super(id, new CompoundPropertyModel<Registration>(regModel))
        // Wrong: RegistrationForm provides its own components
        add(new TextField(&quot;username&quot;));
        add(new TextField(&quot;firstname&quot;));
        add(new TextField(&quot;lastname&quot;));
    }
}

Listing 1

Listing 1 is an example for a poor component. The user of the RegistrationForm must know the internal structure of the markup and component in order to use it.

public class RegistrationPage extends Page {
    public RegistrationPage(IModel<Registration> regModel) {
        Form<?> form = new RegistrationForm(&quot;form&quot;);
        form.add(new SubmitButton(&quot;register&quot;) {
            public void onSubmit() {
                 // do something               
            }
        });
        add(form);
    }
}

<html>
<body>
    <form wicket:id=&quot;form&quot;>
        <!-- These are internal structure information from RegistrationForm -->
        Username <input type=&quot;text&quot; wicket:id=&quot;username&quot;/>
        First name <input type=&quot;text&quot; wicket:id=&quot;firstname&quot;/>
        Last name <input type=&quot;text&quot; wicket:id=&quot;lastname&quot;/>
        <!-- Above new components from page which the user knows  -->
        <input type=&quot;submit&quot; wicket:id=&quot;register&quot; value=&quot;Register&quot;/>
    </form>
</body>
</html>

Listing 2

Listing 2 shows the usage of the poor component in the RegistrationPage. You can see that the input fields firstname, lastname and username get used, even though these components are not added explicitly to the RegistrationPage. Avoid this, because other developers cannot directly see that the components were added in RegistrationPage class.

// Good component
public class RegistrationInputPanel extends Panel{
    public RegistrationInputPanel(String id, IModel<Registration> regModel) {
        super(id, regModel);
        IModel<Registration> compound = new CompoundPropertyModel<Registration(regmodel)
        Form<Registration> form = new Form<Registration>(&quot;form&quot;, compound);
        // Correct: Add components to Form over the instance variable
        form.add(new TextField(&quot;username&quot;));
        form.add(new TextField(&quot;firstname&quot;));
        form.add(new TextField(&quot;lastname&quot;));
        add(form);
    }
}

<html>
<body>
    <wicket:panel>
    <form wicket:id=&quot;form&quot;>
        Username <input type=&quot;text&quot; wicket:id=&quot;username&quot;/>
        First name <input type=&quot;text&quot; wicket:id=&quot;firstname&quot;/>
        Last name <input type=&quot;text&quot; wicket:id=&quot;lastname&quot;/>
    </form>
    </wicket:panel>
</body>
</html>

Listing 3

Listing 3 shows a cleanly cut input component, which provides its own markup. Furthermore you can see the correct usage of a Wicket Form. The components get added by calling form.add(Component) on the instance variable. On the other hand it is allowed to add behaviours and validators over inheritance, because those do not have markup ids which must be bound.

public class RegistrationPage extends Page {
    public RegistrationPage(IModel<Registration> regModel) {
        Form<?> form = new Form(&quot;form&quot;);
        form.add(new RegistrationInputPanel(&quot;registration&quot;, regModel);
        form.add(new SubmitButton(&quot;register&quot;) {
            public void onSubmit() {
              // do something               
            }
        });
        add(form);
    }
}

<html>
<body>
    <form wicket:id=&quot;form&quot;>
        <div wicket:id=&quot;registration&quot;>
           Display the RegistrationInputPanel
        </div>
        <input type=&rdquo;submit&rdquo; wicket:id=&quot;register&quot; value=&quot;Register&quot;/>
    </form>
</body>
</html>

Listing 4

Listing 4 shows the usage of the RegistrationInputPanel. There is no markup of another embedded components present anymore, just markup of components, which get directly added. The RegistrationPage provides its own form, that delegates the submit to all Wicket nested forms which are contained in the component tree.

Put models and page data in fields

In contrast to Struts Wicket pages and components are no singletons, they are stateful and session-scoped. This enables us to store user-specific information within pages and components. The information should be stored in fields. This way you can access the information within a class while avoiding long method signatures only for passing this very same information around. Instances of components can exist over several requests. For example a page with a form which gets submitted and produces validation errors uses the same page instance. Furthermore the same page instance gets used when the user presses the back button of the browser and resubmits this formular again. Information which gets passed by the constructor should be assigned to fields (normally this must be models). When storing information in fields you should consider that the information is serializable, because the pages are stored in Wicket's page map. By default the page map stores the pages on the hard disk. A non serializable object leads to NullPointerExceptions and NonSerializableExceptions. Additionally big data (like binary stuff) should not be stored directly in fields, because this can cause performance losses and memory leaks while serialization and deserialization. In this case you should use the LoadableDetachableModel, which can be assigned to a field, because this provides an efficient mechanism to load and detach data.

Correct naming for Wicket IDs

Naming is for many developers a dispensable thing, but I think it is one of the major topics in software development. With the help of correct naming you identify fastly the business aspects of a software component.

Additionally good naming avoids unneccessary and bad comments.

Bad namings for Wicket-IDs are birthdateTextField, firstnameField and addressPanel. Why? The naming contains two aspects: A technical aspect "TextField" and the business aspect "birthdate". Relevant is just the business aspect because the HTML template already presents the technical aspect through and the Java code presents it by "new TextField("birthdate")". So the technical aspects are already described. Additionally the incorrect naming adds a lot of effort when you do technical refactorings, e.g. if you have to replace a TextField by a DatePicker, in result of it you have to rename the Wicket ID from birthdateTextField to birthdateDatePicker. Another reason for avoiding technical aspects in Wicket IDs is the CompoundPropertyModel. This model delegates the properties to its child components named by Wicket IDs (see listing 3). For example the TextField username calls automatically setUsername() and getUsername() on the Registration object. A naming of the setter setUsernameTextfield() would be very unpracticable here.

Avoid changes at the component tree

You should picture Wicket's component tree as a constant and fixed skeleton which gets revived when its model is filled with data like a robot without brain. Without brain the robot is not able to do anything and is just dead and a fixed skeleton. However when you fill it with data, it becomes alive and can act. There is no need of changing hardware when filling him with data. Components can decide on the state by its own by viewing on the data, e.g. on its visibility. In Wicket you should manipulate the component tree as little as possible. Consequential you should avoid calling methods like Component.replace(Component) und Component.remove(Component). Calling these methods indicates missing usage or misusage of Wicket's models. Furthermore the component trees should not conditionally constructed (see listing 5). This reduces the possibility to reuse the same instance significantly.

// typical struts
if(MySession.get().isNotLoggedIn()) {
    add(new LoginBoxPanel(&quot;login&quot;))
}
else {
    add(new EmptyPanel(&quot;login&quot;))   
}

Listing 5

Instead of constructing LoginBoxPanel conditionally, it is recommend to add the panel always and control the visibility by overriding isVisible(). So the component LoginBoxPanel is responsible for displaying itself. We move the responsibility into the same component, which executes the login. Brilliant! Business logic cleanly encapsulated. There is no decision from outside, the component handles all the logic. You can see another example in "Implement visibilities of components correctly".

Implement visibilities of components correctly

Visibility of site parts is an important topic. In Wicket you control the visibility of components over the methods  isVisible() and setVisible(). These methods are within Wicket's base class Component and therefore it regards every component and page. Let's have a look to a concrete example of LoginBoxPanel. The panel just gets displayed when the user is not logged in.

// Poor implementation
LoginBoxPanel loginBox = new LoginBoxPanel(&quot;login&quot;);
loginBox.setVisible(MySession.get().isNotLoggedIn());
add(loginBox);

Listing 6

Listing 6 shows a poor implementation, because a decision of visibility is made while instanciating the component. Again in Wicket instances of components exist over several requests. To reuse the same instance you have to call loginBox.setVisible(false). This is very unhandy, because we always have to call setVisible() and manage the visibility. Furthermore you are going to duplicate the states, because visible is equal to "not logged in". So we have two saved states, one for the business aspect "not logged in" and one for the technical aspect "visible". Both is always equal. This approach is error-prone and fragile, because we always have to attend that the correct information will be set at every time. But this is often forgotten, because the logic is wide spread over the code. The solution is the Hollywood-Principle: "Don't call us, we'll call you.". Take a look at the diagram, there is an application flow with some calls. We avoid three calls through the Hollywood-Principle and we just have to instanciate the LoginBoxPanel.

Login Panel

 

public class LoginBoxPanel {
    // Konstruktor etc
    @Override
    public boolean isVisible() {
        return MySession.get().isNotLoggedIn();
    }
};

Listing 7

In listing 7 the control over visibility has got inverted, now the LoginBoxPanel decides over the visibility by its own. On each call of isVisible() there is a refreshed interpretion of the login state. Concluding there is no out-dated information state additionally saved. The logic is centralised in one line code and not spread application wide. Furthermore you can easily identify that the technical aspect isVisible() correlates to the business aspect "logged in". The same rules can be applied to the method isEnabled(). If isEnabled() returns false the components get displayed gray. Forms which are within an inactive or invisible component do not get executed. Sometimes there are cases you cannot avoid to call the methods setVisible() and setEnable(). An example: The user presses a button to display an inlined registration form. In general you can apply the following rules: Data driven components override these methods and delegates to the data model. User triggered events call the method setVisible(boolean). As well you can  override these methods by inline implementations (see listing 8).

new Label(&quot;headline&quot;, headlineModel) {
    @Override
    public boolean isVisible() {
        // Hidden headline if text contains &quot;Berlosconi&quot;
        String headline = getModelObject();
        return headline.startWith(&quot;Berlosconi&quot;);
    }
}

Listing 8

Note: Some people say that overriding isVisible() is bad: http://goo.gl/6aCUv. The method isVisible() gets called very often (more than once at each request!), so you have to ensure that the calls within isVisible() are cheap. The main point is that the visibility of a component should be controlled by its own and not be controlled by other components. This avoids a wide-spreaded logic over the whole application. Another way you can realize this is to override onConfigure() and set the visibility there. This method gets called once on each request.

Always use models

Always use models! Do not pass raw objects directly to components. Instances of pages and components can exist over several requests. If you use raw objects, you cannot replace them later. An example is an entity which gets loaded at each request within a LoadableDetachableModel. The entity manager creates a new object reference, but the page would keep the obsolete instance. Always pass IModel in the constructor of your components (see listing 9).

public class RegistrationInputPanel extends Panel{
    // Correct: The class Registration gets wrapped by IModel
    public RegistrationInputPanel(String id, IModel<Registration> regModel) {
        // add components
    }
}

Listing 9

The solution in listing 9 could have every implementation in the model. Beginning with the class Model over the PropertyModel and an own implementation of LoadableDetachableModel, which loads and persists the values automatically. The model implementations get very easy to replace. You – as user – just want to know: If I call IModel.getObject(), I will get an object of type Registration. Where the object comes from is the charge of the model implementation and the calling component. For example you can pass the model while instanciating the component. If you avoid using models, you will get the dilemma to modify the component tree sooner or later. Whereby you duplicate states  and thus produce unmaintable code. Additionally you should use models by reason of serialization. Objects which get stored in fields of pages and components get serialized and deserialized on each request. This could be inperformant in some cases.

Do not unpack models within the constructor hierarchy

Avoid unpacking models within the constructor hierarchy, that means do not call IModel.getObject() within the constructor hierarchy. As aforementioned a page instance can exist over several page requests, so you can hold an obsolete and redundant infomation. It is allowed to unpack Wicket Models at events (user actions), that are methods like onUpdate(), onClick() or onSubmit() (see listing 10).

new Form(&quot;register&quot;) {
    public void onSubmit() {
        // correct, unpack model in an event call
        Registration reg = registrationModel.getObject()
        userService.register(reg);
    }
}

Listing 10

An additional possibility to unpack models is through overriding methods like isVisible(), isEnabled() or onBeforeRender().

Pass-trough models to components of extending class

Pass-through models to the parent component. So you ensure, that at the end of every request the method IModel.detach() get called. Those method is responsible for a data cleanup. Another example: you have your own model implemented which persists the data in the detach() method. So the call of detach() is neccessary that your data gets persisted. You can see an exemplary pass-through to the super constructor at listing 11.

public class RegistrationInputPanel extends Panel{
    public RegistrationInputPanel(String id, IModel<Registration> regModel) {
        super(id, regModel)
        // add components
    }
}

Listing 11

Validators must not change any data or models

Validators just should validate. For example: a bank account form which has a BankFormValidator. This validator checks the bank data over a webservice and corrects the bank name. Nobody would expect that a validator modifies information. Such logic has to be located in Form.onSubmit() or in the event logic of a button.

Do not pass components to constructors

Do not pass components or pages to constructors of other components.

// Bad solution
public class SettingsPage extends Page {
    public SettingsPage (IModel<Settings> settingsModel, final Webpage backToPage) {
        Form<?> form = new Form(&quot;form&quot;);
        // add components
        form.add(new SubmitButton(&quot;changeSettings&quot;) {
            public void onSubmit() {
               // do something   
               setResponsePage(backToPage)           
            }
        });
        add(form);
    }
}

Listing 12

See listing 12: The SettingsPage expects in the constructor the page which should be displayed after a successful submit. This solution works, but is very bad style and unflexible. You have to know at the instanciation of SettingsPage where you want to redirect the user. This requires a predetermied order of instanciation. Better it is to order the instanciation after business logic (e.g. the order in the HTML template).  Furthermore you need an unnecessary instance of the next page, which could not be displayed. The solution is the hollywood principle again. For this you create an abstract method or a hook (listing 13).

// Good solution
public class SettingsPage extends Page {
    public SettingsPage (IModel<Settings> settingsModel) {
        Form<?> form = new Form(&quot;form&quot;);
        // add components
        form.add(new SubmitButton(&quot;changeSettings&quot;) {
            public void onSubmit() {
               // do something
               // e.g. persist data   
               onSettingsChanged()   
            }
         });
         add(form);
    }

    // Hook
    protected void onSettingsChanged() {
    }
}

// The usage of the new component
Link<Void> settings = new Link<Void>(&quot;settings&quot;) {
    public void onClick() {       
        setResponsePage(new SettingsPage(settingsModel) {
            @Override
            protected void onSettingsChanged() {
               // Referenz der aktuellen Seite
               setResponsePage(MyPage.this);
            }
        });
    }
}
add(settings);

Listing 13

The solution from listing 13 has more code, but is more flexible and significant. We can see there is an event onSettingsChanged() and this event is called after a successful change. Furthermore there is the possibility to execute more code just than set the back page. For example you can display messages or persist information.

Use the Wicket session only for global data

The Wicket session is your own extension from Wicket's base session. It is fully typed. There is no map structure to store information unlike the servlet session. You just should use Wicket's session for global data. Authentification is a good example for global data. The login and user information is required on nearly each page. For a blog application it would be good to know, whether the user is an author who is allowed to compose blog entries. So you are able to hide or or show links to edit a blog entry. In general you should store the whole authorization logic in Wicket's session, because it is a global thing and you would expect it there. Data of forms and flows which span over several pages should not stored in the session. This data can be passed from one page to the next over the constructor (listing 14). As a consequence of this, the models and data have a defined life cycle over the page flow.

public class MyPage extends WebPage {
    IModel<MyData> myDataModel

    public MyPage(IModel<MyData> myDataModel) {
        this.myDataModel = myDataModel;
        Link<Void> next = new Link<Void>(&quot;next&quot;) {
             public void onClick() {       
                  // do something
                  setResponsePage(new NextPage(myDataModel));
             }
        }
        add(next);
    }
}

Listing 14

As you see in listing 14 you should pass concrete information to the page. All models can be stored in fields, because Wicket pages are userspecific instances and no singletons in contrast to Struts. The big advantage of this approach is, that the data gets automatically cleaned up when user completes or exits the flow early. No manually cleanup anymore! This is quasi a garbage collector for your session.

Do not use factories for components

The factory pattern is an useful pattern, but unsuitable for Wicket components.

public class CmsResource {
   public Label getCmsLabel(String markupId, final String url) {
       IModel<String> fragment = new AbstractReadOnlyModel<String>() {
          @Override
          public String getObject() {
             return loadSomeContent(url);
          }
       };
       Label result = new Label(markupId, fragment);
       result.setRenderBodyOnly(true);
       result.setEscapeModelStrings(false);
       return result;
   }

   public String loadContent(String url) {
      // load some content
   }
}

// create the component within the page:
public class MyPage extends WebPage {
   @SpringBean
   CmsResource cmsResource;
   
   public MyPage() {
      add(cmsFactory.getCmsLabel(&quot;id&quot;, &quot;http://url.to.load.from&quot;));
   }
}

Listing 15

The approach in listing 15 for adding a label from the CmsFactory to a page seems to be initially ok, but brings some disadvantages. There is no possibility anymore to use inheritance. Furthermore there is no possibility to override isVisible() and isEnabled(). The factory could be also a spring service which instanciates the component. A better solution is to create a CmsLabel (listing 16).

public class CmsLabel extends Label {
   @SpringBean
   CmsResource cmsResource;
   public CmsLabel(String id, IModel<String> urlModel) {
      super(id, urlModel);
      IModel<String> fragment = new AbstractReadOnlyModel<String>(){
         @Override
         public String getObject() {
            return cmsResource.loadSomeContent(urlModel.getObject());
         }
      };
      setRenderBodyOnly(true);
      setEscapeModelStrings(false);
   }
}

// create the component within a page
public class MyPage extends WebPage {
   public MyPage() {
      add(new CmsLabel(&quot;id&quot;, Model.of(&quot;http://url.to.load.from&quot;)));
   }
}

Listing 16

The label from listing 16 is clearly encapsulated in a component without using a factory. Now you can easily create inline implementations and override isVisible() or other stuff. Now someone could say "I need a factory to initialize some values in the component, e.g. a spring service.". For this you can create a implementation of IComponentInstantiationListener. This listener gets called on the super-constructor of every component. The most popular implementation of this interface is the SpringComponentInjector which injects spring beans in components when the fields are annotated with @SpringBean. You can easliy write and add your own implementation of IComponentInstantiationListener. So there is no reason using a factory anymore. More information about the instanciation listener is located in Wicket's javadoc.

Every page and component expects a test

Every page and component should have a test. The simplest test just renders the component and validates its technical correctness. For example a child component should have a matching wicket id in the markup. If the wicket id is not correctly bound – through a typo or it was just forgotten – the test will fail. An advanced test could test a form, where a backend call gets executed and validated over a mock. So you can validate your component's behaviour. This is a simple way to detect and fix technical and business logic bugs while the build process. For the test driven development approach, you can use wicket quite well. Lets say you have a page so you can validate the correctness of the page by running the unit test. If you run the unit test which fails and shows a message that the wicket id not bound, so you will avoid an unneccessary server startup, because a server startup takes longer than running a unit test. This reduces the development turnaround. A disadvantage is the difficult testing possibility of AJAX components. However the testing possibilites of Wicket are much more than in other web frameworks.

Avoid interactions with other servlet filters

Try to get as long as possible within the Wicket world. Avoid the usage of other servlet filters. For this you can use the RequestCycle and override the methods onBeginRequest() and onEndRequest(). You can apply the same to the HttpSession. The equivalent in Wicket is the WebSession. Just extend the WebSession and override the newSession()-method from the Application class. There are very few reasons to access the servlet interfaces. An example could be to read an external cookie to authentificate a user. The parts should encapsulated well and minimized. For this example you could put the handling in the Wicket session, because this is an authentification.

Cut small classes and methods

Avoid monolithic classes. Often I have seen that developers put the whole stuff into constructors. These classes are getting very unclear and chaotic, because you use inline implementations over serveral levels. It is recommended to group logical units and extract methods with a correct business naming. This enhances the clarity and the understandability of the business aspect. When a developer navigates to a component, he is not interested in the technical aspect at first, however he just need the business aspect. To retrieve technical information of a component you can navigate to the method implementation. In case of doubt you should consider to extract seperate components. Smaller components increase the chance of reuse and make the testability easier. Listing 17 shows an example of a possible structuring.

public class BlogEditPage extends WebPage {
    private IModel<Blog> blogModel;

    public BlogEditPage(IModel<Blog> blogModel) {
        super(new PageParameters());
        this.blogModel = blogModel;
        add(createBlogEditForm());
    }

    private Form<Blog> createBlogEditForm() {
        Form<Blog> form = newBlogEditForm();
        form.add(createHeadlineField());
        form.add(createContentField());
        form.add(createTagField());
        form.add(createViewRightPanel());
        form.add(createCommentRightPanel());
        form.setOutputMarkupId(true);
        return form;
    }
    
    // more methods here
}

Listing 17

The argument "Bad documentation"

Often I have heard that Wicket has a bad documentation. This argument is just particular correct. There are a lot of code samples and snippets which can be used as code templates. Furthermore there is a big community that answers complex questions in shortest time. In Wicket it is very hard to document everything, because nearly everything is extensible and replaceable. If a component is not completely suitable, you will extend or replace it. The work with Wicket is a permanent navigating through the code. For example the validators. How can I find all navigators that exists? Open the interface IValidator (Eclipse Ctrl + Shift + T) and then open the type hierachy (Crtl + T). Now we are seeing all the validators existing in Wicket and our project.

Type Hierachy

Conclusion

These advices should help you to write better and more maintainable code in Wicket. All described methodologies were already proved in a few Wicket projects. If you follow these advices, your Wicket projects will get future-proof and successful hopefully.

Links:
1. http://wicket.apache.org/ (Apache Wicket)
2. http://wicketstuff.org/wicket14/ (Wicket Examples)
3. http://en.wikipedia.org/wiki/Hollywood_Principle

Thanks to Daniel Bartl for the correction.

Adaptive Test Execution With Gradle And Spring

One of the customizations that we wanted to have as part of our regular build process is to be able to detect which required external services are available in the concrete build execution environment at build time and to adapt the test execution accordingly. This is especially important in regards to the medium and large tests (as defined by google) you might want to execute as part of your build.

Test Classification By Google

It’s medium and large tests that will fail and lead to a broken build in case some of the required external services are not available at build execution time. Having a broken build of this kind actually reflects 2 things:

  1. That your build process, and not necessarily your software package that it’s trying to build, is currently broken.
  2. That the software package that could be built in case you skip the failing medium and large tests possibly does not fulfill all quality requirements that your build process usually requires and should be marked as such accordingly.

We simply wanted to have a build process that is able to adapt according to the execution environment at hand and always provide us with the best possible build under given circumstances. Maybe it’s a beautiful sunny day and you want to work in a park on your notebook where your build execution environment might possibly be limited (your “wellness” environment might likely be improved though ;) ) or you simply don’t want to have a completely broken build while some other member of your team is trying to get the database online again.

Buildtime Environment Detection

Thanks to the flexibility of Gradle and a single nice feature of Spring TestContext framework creating this kind of adaptive build process was very simple indeed.

The following example will show how you can easily verify whether your database instance (in our case MongoDB) is available at build execution time and how you can adapt your build execution accordingly.

First step is to define a dependency of our build script to a library that will be used in order to verify whether required database instance is currently running:

buildscript {

    dependencies {
        classpath group: 'com.gmongo', name: 'gmongo', version: '0.7'
    }

    repositories {
        mavenCentral()
    }
}

We then define an additional method as part of our build script that will use previously defined library accordingly:


/**
 * Verifies what environment services required for successful test execution are available at buildtime:
 * <ul>
 *     <li>
 *         Verifies whether there is an according MongoDB instance running in the local test environment
 *         listening on the default port of MongoDB: 27017.
 *         Note: GMongo driver initialization fails with IOException wrapped inside of
 *         com.mongodb.MongoInternalException in case there is no running MongoDB instance found.
 *     </li>
 * <ul>
 *
 * @return a Map with according entry for each of the required environment services.
 */
Map defineEnvironmentForTestExecution() {
    def env = new HashMap()
    try {
        new GMongo()
        env.put("CI-MongoDBAvailable", "true")
    } catch (Throwable throwable) {
        env.put("CI-MongoDBAvailable", "false")
    }
    return env
}

Now a Map of identified environment properties has to be included into a Map of system properties defined for each test execution (here defined for multi-module gradle build as part of the subprojects configuration):


subprojects {
   envProps = defineEnvironmentForTestExecution()

    test {
        systemProperties = envProps
    }
}

Additionally, we customize the manifest creation since we want to include the information about the environment that the package has been built in into the MANIFEST file of the package itself (here defined for one of the subprojects being packaged as a WAR archive):


    war {
        manifest {
            attributes envProps
        }
    }

Since envProps has been defined in subprojects section previously, it can be referenced in each of the subprojects accordingly. This will ensure that all information about the environment that the artifact has been created in, will be described in its META-INF/MANIFEST.MF file:

Manifest-Version: 1.0
CI-MongoDBAvailable: false

The only code change that we have to apply in order to get our adaptive test execution that reacts upon the envProps that have been calculated and included into a list of system properties is to annotate our tests with the according @IfProfileValue annotation provided by Spring framework:


@ContextConfiguration(locations = "classpath:WEB-INF/spring-mvc-context.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringRestContextTest {

    @Autowired
    MongoTemplate mongoTemplate;

    @Test
    @IfProfileValue(name = "CI-MongoDBAvailable", value = "true")
    public void testSpringRestContextInitialization() {
        Assert.assertNotNull(mongoTemplate);
    }
}

All tests annotated as described above will now be executed only in case the according MongoDB instance is available in the current build execution environment.

Additionally to providing detailed information about the build environment in the MANIFEST file of the artifact itself, one could easily enough additionally mark the created artifact by modifying its very name to something like $YourArtifactBaseName.PARTIALLY.TESTED.ONLY.war or simply changing its version to 1.0.0.PARTIALLY.TESTED.SNAPSHOT for example.

You could basically mark the artifact in whatever ways you like, given of course that you have already migrated your build process to Gradle ;) .

Lost In Redirection With Apache Wicket

Quite a few teams have already got stuck into the following problem when working with wicket forms in a clustered environment while having 2 (or more) tomcat server with enabled session replication running.

In case of invalid data being submitted with a form instance for example, it seemed like according error messages wouldn’t be presented when the same form page gets displayed again. Sometimes! And sometimes they would! One of those nightmares of rather deterministic programmer’s life. This so called Lost In Redirection problem, even if it looks like a wicket bug at first, is rather a result of a default setting in wicket regarding the processing of form submissions in general. In order to prevent another wide known problem of double form submissions, Wicket uses a so called REDIRECT_TO_BUFFER strategy for dealing with rendering a page after web form’s processing (@see IRequestCycleSettings#RenderStrategy).

What does the default RenderStrategy actually do?

Both logical parts of a single HTTP request, an action and a render part get processed within the same request, but instead of streaming the render result to the browser directly, the result is cached on the server first.

Default Form Processing in Wicket

Wicket will create an according BufferedHttpServletResponse instance that will be used to cache the resulting HttpServletResponse within the WebApplication.

WebApplication Caching Buffered Responses

After the buffered response is cached the HTTP status code of 302 get’s provided back to the browser resulting in an additional GET request to the redirect URL (which Wicket sets to the URL of the Form itself). There is a special handling code for this case in the WicketFilter instance that then looks up a Map of buffered responses within the WebApplication accordingly. If an appropriate already cached response for the current request is found, it get’s streamed back to the browser immediately. No additional form processing happens now. The following is a code snippet taken from WicketFilter:

			// Are we using REDIRECT_TO_BUFFER?
			if (webApplication.getRequestCycleSettings().getRenderStrategy() == IRequestCycleSettings.REDIRECT_TO_BUFFER)
			{
				// Try to see if there is a redirect stored
				// try get an existing session
				ISessionStore sessionStore = webApplication.getSessionStore();
				String sessionId = sessionStore.getSessionId(request, false);
				if (sessionId != null)
				{
					BufferedHttpServletResponse bufferedResponse = null;
					String queryString = servletRequest.getQueryString();
					// look for buffered response
					if (!Strings.isEmpty(queryString))
					{
						bufferedResponse = webApplication.popBufferedResponse(sessionId,
							queryString);
					}
					else
					{
						bufferedResponse = webApplication.popBufferedResponse(sessionId,
							relativePath);
					}
					// if a buffered response was found
					if (bufferedResponse != null)
					{
						bufferedResponse.writeTo(servletResponse);
						// redirect responses are ignored for the request
						// logger...
						return true;
					}
				}
			}

So what happens in case you have 2 server running your application with session replication and load balancing turned on while using the default RenderStrategy described above?

Since a Map of buffered responses is cached within a WebApplication instance that does not get replicated between the nodes obviously, a redirect request that is suppose to pick up the previously cached response (having possibly form violation messages inside) potentially get’s directed to the second node in your cluster by the load balancer. The second node does not have any responses already prepared and cached for your user. The node therefore handles the request as a completely new request for the same form page and displays a fresh new form page instance to the user accordingly.

Clustering Without Sticky Sessions

Unfortunately, there is currently no ideal solution to the problem described above. The default RenderStrategy used by Apache Wicket simply does not work well in a fully clustered environment with load balancing and session replication turned on. One possibility is to change the default render strategy for your application to a so called ONE_PASS_RENDER RenderStrategy which is the more suitable option to use when you want to do sophisticated (non-sticky session) clustering. This is easily done in the init method of your own subclass of Wicket’s WebApplication :

    @Override
    protected void init() {
        getRequestCycleSettings().setRenderStrategy(
            IRequestCycleSettings.ONE_PASS_RENDER);
    }

ONE_PASS_RENDER RenderStrategy does not solve the double submit problem though! So this way you’d only be trading one problem for another one actually.

You could of course turn on the session stickiness between your load balancer (apache server) and your tomcat server additionally to the session replication which would be the preferred solution in my opinion.

Clustering With Sticky Sessions Turned On

Session replication would still provide you with failover in case one of the tomcat server dies for whatever reason and sticky sessions would ensure that the Lost In Redirection problem does not occur any more.

How to integrate Google Maps in a website using jQuery in 3 steps

comSysto Google Maps

There are lots of powerful jQuery plugins out there. Let’s have a look how jQuery’s Plugin jMaps can help us to integrate a Google Maps goodie in a website. jMaps is originally developed by DigitalSpaghetti and can be downloaded from the plugin section on jQuery.com. So let’s start:

Step 1: Google Maps Key
Get google maps key to access google maps service and add following tag to your website:

<script src=”http://maps.google.com/maps?file=api&v=2&key=YOUR_KEY_HERE” type=”text/javascript”></script>

Remember that for displaying Google Maps in your local environment it is not necessary to enter a valid key, but once you are ready to go your maps widget will not work without the key. Google uses it to prevent fraud and misuse of the API and assigns it to each person individually.

Step 2: Modify your HMTL
First you need to refer to jQuery library and to downloaded jMaps file. Add following two tags with your individual file- and folder names (and paths) to your HTML file

<script type=”text/javascript” src=”scripts/jquery-1.4.4.min.js”></script>
<script type=”text/javascript” src=”scripts/jquery.jmap.js”></script>

..and provide a DIV container (feel free to use any other HTML tag) where you want your Google Maps widget to be inserted. For instance:

<div id=”googleMap”></div>

Step 3: Call the jMap function
Now all you need to do is to call the jMap function and feed it with map data you want to be displayed. There are several way to do it. You can either insert an internal script snippet into your HTML file, or you can create a new external JavaScript document and call the jMap function using the $(document).ready(function() {}). I prefer to link to external JavaScript files just before the closing </body> tag at the end of the DOM. Doing this you can skip the $(document).ready - stuff, since this is only telling the browser: “Wait till you have the complete DOM”. Since the script link appears on the end of the DOM the DOM is already ready and you can give your fingers a break. So lets fire the jMap:

$(‘#googleMap’).jmap(‘init’, {
mapCenter:[48.173224, 11.530809],
mapShowjMapIcon: false,
mapZoom: 12,
mapControlSize: ‘large’,
mapEnableDoubleClickZoom: true
});
$(‘#googleMap’).jmap(‘addMarker’, {
pointLatLng:[48.173224, 11.530809]
});


Lets have a look what all this Options stand for
With the first line of code you select the HTML tag with id=”googleMap” using jQuery’s CSS Selector ‘ #googleMap’ and fire the jMap function giving it a Object Literal with several attributes. Most of them are self explaining except of those magic numbers for the mapCenter. Those coordinates you can get on the Google Maps page by entering wished address into the maps form. Once Google Maps has displayed the requested section of the map you can get the according coordinates by entering following magic spell into the location bar of your browser:

javascript:void(prompt(”,gApplication.getMap().getCenter()));

Google Maps will than alert the needed coordinates. All you need to do here is to replace of the “(” and “)” by “[" and "]“and to assign the value to the mapCenter attribute. The further function ‘addMarker’ will get you a marker on the map.

You can see how this looks like with this DEMO: http://www.comsysto.com/Imprint.htm

Tagged , , ,

Apache Wicket – Best practices

Apache Wicket erfreut sich immer steigender Popularität und findet mehr und mehr Einsatz in Projekten. Dank der Mächtigkeit von Wicket lassen sich viele Features einfach und schnell realisieren. Für die Umsetzung dieser Features gibt es viele Wege. Dieser Artikel bietet einige Kochrezepte zum richtigen, effizienten und nachhaltigen Umgang mit Apache Wicket.

Dieser Artikel richtet sich an Entwickler, die bereits erste Erfahrungen mit Apache Wicket gesammelt haben. Entwickler, die in Wicket-Welt einsteigen tun sich oftmals schwer, weil sie Entwicklungsmethoden aus der JSF- oder Struts-Welt adaptieren. Diese Frameworks setzen vorrangig auf prozedurale Programmierung. Wicket hingegen setzt massiv auf Objektorientierung. Also vergessen Sie die Struts und JSF-Patterns, sonst werden Sie nicht lange Freude an Wicket haben.

Continue reading

Tagged , ,

Verstärkung gesucht – Data Warehouse Developer/DBA (m/w)

Your Geek Crowd
Die Suche nach neuen Kollegen mit großem fachlichen und menschlichen Potenzial sehen wir als eine unserer wichtigsten Daueraufgaben. Unser Motto dabei lautet: “Das Ganze ist mehr als die Summe seiner Teile”. Stolz können wir jetzt schon behaupten, ein tolles Team zu sein: jung aber kompetent, unkompliziert und trotzdem professionell, individuelle Stärken hervorhebend und gleichzeitig die Gemeinsamkeiten stärkend.

Als Data Warehouse Developer/DBA bei comSysto werden Sie in einem kleinen Team mit erfahrenen Consultants, hochqualifizierten Oracle-Technologieexperten und kreativen Softwareentwicklern zusammenarbeiten. Gemeinsam mit unseren Kunden werden Sie komplexe Quellsysteme analysieren, Key Performance Indicators (KPIs) sowie die sich daraus ableitende DWH-Modelle definieren und diese mit führenden Datenbanksystemen sowie ETL-Tools implementieren. Sie lernen verschiedene interessante Branchen und führende Unternehmen kennen, während Ihre methodischen und technologischen Skills stetig erweitert und vertieft werden.

Was Sie unbedingt mitbringen sollten:
• Theoretische Kenntnisse und praktische Erfahrung in ER- und relationaler
DWH-Datenmodellierung
• Erste praktische Erfahrungen mit Oracle DBMS oder einem gängigen ETL-Tool
• Ausgewogenes Verhältnis aus technischen und Business-Skills
• Gute Team- und exzellente Kommunikationsfähigkeit, sicheres Auftreten, Lösungsorientierung und ausgeprägtes analytisches Denken
• Reisebereitschaft
• Offenheit gegenüber neuen Ideen und hohe Lernbereitschaft

Wünschenswert:
• Mehrjährige praktische Erfahrung mit Oracle DBMS und PL/SQL oder einem führenden ETL Tool wie Informatica PowerCenter, Oracle Warehouse Builder/Data Integrator
• Oracle Certified Professional (OCP) oder ähnliche Zertifizierung
• Praktische Erfahrung und Zertifizierung in agilen Entwicklungsmethoden oder klassischem Projektmanagement
• Fremdsprachenkenntnisse

Wir bieten Ihnen:
• Leistungsorientierte Entlohnung (immer nach dem Win-Win-Prinzip)
• Ausführliche Inhouse und externe Weiterbildungsmaßnahmen für Ihre Hard- und Soft-Skills
• Offene und einfache Kommunikation sowie kurze Entscheidungswege
• Viel Gestaltungsspielraum in Ihrem Arbeitsleben und die damit verbundene Verantwortung
• Interessante Kollegen und Projekte

Haben wir Ihr Interesse geweckt? Die Aufgaben entsprechen Ihren Vorstellungen von einer anspruchsvollen und eigenverantwortlichen Tätigkeit? Dann freuen wir uns auf Ihre aussagefähigen Bewerbungsunterlagen per Mail auf job[at]comsysto.com!

Follow

Get every new post delivered to your Inbox.