Die ruhrjug ist wieder da!

Nach gut anderthalb Jahren Pause haben wir am 27.11.2014 die Java User Group Essen, kurz: ruhrjug, gemeinsam mit infaktum Veranstaltungen wieder zum Leben erweckt: mit einem Vortragsabend zum Thema “Rapid Application Development mit AngularJS und Grails” am OC Standort in Essen.

Unsere beiden “Vortragsroutiniers” Stefan Glase und Stefan Scheidt präsentierten ihre Beiträge in gewohnt unterhaltsamer und informativer Weise. Zunächst gab Stefan Scheidt in 30 Minuten mit ein paar Folien und viel Live Coding eine kurze Einführung in AngularJS, anschließend tat es ihm Stefan Glase mit einer Kurzvorstellung von Grails gleich. Danach dann der wirklich spannende Teil mit der Frage: Wie kann man AngularJS und Grails zusammenbringen? Es wurde gezeigt, wie man mit Grails ein REST-Endpoint für ein Domänen-Objekt bereitstellt und diesen in Angular mittel ngResource-Objekten konsumiert. Kurz wurde der Umgang mit der “Same Origin Policy” diskutiert und dann zwei Vorgehensweisen zur Projektstruktur vorgestellt: zunächst eine getrennte Behandlung von Grails und Angular in jeweils separaten Projekten und abschließend das Einbetten der Angular-App in die Grails-Applikation mit Hilfe des Grails Asset Pipeline PluginsHier gibt es die Folien zum Vortrag.

Wie gut Themen und Präsentation beim Publikum ankamen, zeigten die vielen interessierten Nachfragen während des Vortrags, die teilweise aus dem Plenum selbst beantwortet wurden. So überraschte es auch nicht, dass sich im Anschluss viele engagierte Diskussionen ergaben, bei denen sich die Speaker und einige anwesende Kollegen und Teilnehmer als kompetente und auskunftsfreudige Ansprechpartner unter Beweis stellten. Dass der ursprünglich geplante Bummel über den Weihnachtsmarkt ausfiel, bedauerte daher niemand. Die Veranstaltung endete nach drei spannenden Stunden gegen 21 Uhr.

Zu Beginn der Veranstaltung haben wir die Anwesenden eingeladen, an der weiteren Wiederbelebung und Weiterentwicklung der ruhrjug aktiv teilzunehmen. Hier gibt es nicht nur die Möglichkeit, selbst Themen zu platzieren, sondern man kann sich auch Themen wünschen. Natürlich ist auch Unterstützung in Form von Sponsoring herzlich willkommen. Thematische Ideen für Folgeveranstaltungen gibt es schon einige: Zum Thema Microservices (docker) hat sich mit Peter Roßbach auch schon ein prominenter Speaker angeboten.

An dieser Stelle möchten wir auch die Java-Interessierten unter euch zur Beteiligung aufrufen: Bitte macht mit und steigt mit uns in die Detailplanung für regelmäßige Folgeveranstaltungen ein und meldet euch mit Vorschlägen oder Wünschen bei info@ruhrjug.de. Momentan wird an einen etwa vierteljährlichen Rhythmus für die Veranstaltung gedacht.

Zum Abschluss noch ein paar Impressionen vom Event:

ruhrjug-impressionen

Veröffentlicht unter Java | Verschlagwortet mit , , , , | Hinterlasse einen Kommentar

Using log4j 2 in an Oracle ADF 12c Application

Configure ADF12c application to work with log4j2

One of our customers had the requirement to use log4j 2 in his ADF 12c application. When executing his code

import java.io.Serializable;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import javax.faces.event.ActionEvent;
import oracle.adf.view.rich.component.rich.input.RichInputText;

public class LoggingBean implements Serializable {
    private static final long serialVersionUID = 1L;
    private static final Logger log = LogManager.getLogger(LoggingBean.class.getName());
   
    public LoggingBean() {
    }

    public void logText(ActionEvent actionEvent) {
        log.info("Text to log");
    }

}

an UnsupportedOperationException was thrown.

[...] Caused by: java.lang.UnsupportedOperationException: setXIncludeAware 
is not supported on this JAXP implementation or earlier: 
class oracle.xml.jaxp.JXDocumentBuilderFactory 
at javax.xml.parsers.DocumentBuilderFactory.setXIncludeAware(DocumentBuilderFactory.java:614)

To resolve this issue you can configure your ADF12c application to use a specific implementation of DocumentBuilderFactory. This is quite simple and straightforward. Just configure your weblogic specific deployment descriptor tor use com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl as application’s DocumentBuilderFactory implementation. This is what worked for us. Other implementations of DocumentBuilderFactory might be a valid, too. To configure the DocumentBuilderFactory you can use JDeveloper tooling:

weblogic-application_docbuild

This will put the following lines into your weblogic-application.xml:

  
 <xml>
   <parser-factory>
     <document-builder-factory>
       com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
     </document-builder-factory>
   </parser-factory>
 </xml>

To dodge possible other unsupported operations, we also provided values for SAX Parser Factory and Transformer Factory:

  • SAX Parser Factory: com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
  • Transformer Factory: com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl

The screenshot below shows our configuration:

weblogic-application.xml

Prerequisites

The following JARs have been added to project’s classpath:

  • log4j-api-2.1.jar
  • log4j-core-2.1.jar
  • log4j-web-2.1.jar

These files are contained within the log4j2 download package.

Follow ups

Without providing any configuration file log4j2 will log our messages on console. To configure another behavior just put a configuration file into your project’s src directory (e.g. <path of model project>/Model/src or <path of ViewController project>/ViewController/src).  The  configuration file itself can be written in XML, JSON, or YAML. For more information on the expected syntax have a look at log4j2’s official documentation.

Veröffentlicht unter JDeveloper, Oracle ADF, Oracle FMW | Verschlagwortet mit , , , , | 2 Kommentare

Using the Camunda Workflow API to control timer events and process instances

This post shows an example of using the Camunda Workflow API. It can be a handy and easy-to-use interface, if you want to dive into your workflow environment a little deeper.

In a recent client project, we were confronted with the need to dynamically switch on and off a timer event, triggering email reminders for the user. The interesting part was that this should also happen for other process instances of the same user.  Since a single process instance did not know any of the other “siblings”, the Camunda Workflow API came in handy.

To help you understand, we want to show you a model of the facilitated business use case (Image 1).

Lease-A-Car Business Process

Image 1 – Lease-A-Car Business Process

 

Imagine we want to lease a car. Let’s say we are interested in 3 different manufacturers so we configure 3 different cars and start one leasing request process for each one of these cars.

After our leasing company calculated the monthly rates, we want to be able to select the car with the most reasonable rate. The 3 processes will remind us to do so, in case we wait too long.

So far so good. Imagine now, we choose one rate out of our 3 inquiries and the relevant process instance will make sure next step “check credit-worthiness” is triggered. Besides that, the two other instances remain at the point to choose the rate. So while we wait and hope that our credit-worthiness goes through, we still get emails to remind us checking the rates for cars, we aren’t interested in any more…

Why don’t we just delete the other instances? Good question: We had the requirement, that the specific rate is part of the credit-worthiness check. In case it fails, the customer might want to order another car (hence instances are still ticking at this point). But yes, to avoid instance-zombies after a car was successfully ordered, the remaining instances will be deleted at the end of the process.

This requirement resulted in the following considerations. To stop reminder emails, we have to filter active timer events and suspend the resultset. To do so, we need three types of information.

  • CustomerId (to get all instances for)
  • processDefinitionKey (to distinguish from instances of other processes)
  • BoundaryEventName (to request the right subset)

This is the code, we came up with:

public void suspendTimerEventInOtherProcessInstances(String processDefinitionKey,
  Long customerId, String boundaryEventName) {
    List<Job> timerJobs =
    getTimersForProcessByCustomerIdAndJobName(processDefinitionKey, customerId, boundaryEventName);

    for (Job job : timerJobs) {
     managementService.suspendJobById(job.getId());
    }
 }

private List<Job> getTimersForProcessByCustomerIdAndJobName(String processDefinitionKey,
  Long customerId, String boundaryEventName) {
    List<ProcessInstance> processInstanceList =
      runtimeService.createProcessInstanceQuery().processDefinitionKey(processDefinitionKey)
      .variableValueEquals(ProcessVariables.CUSTOMER_ID, customerId).list();

  List<Job> jobList = new ArrayList<Job>();
   for (ProcessInstance processInstance : processInstanceList) {
     List<Job> timerJobs =
     managementService.createJobQuery().processInstanceId(processInstance.getId()).timers()
     .active().list();

  for (Job job : timerJobs) {
    if (((org.camunda.bpm.engine.impl.persistence.entity.TimerEntity) job)
    .getJobHandlerConfiguration().equals(boundaryEventName)) {
      jobList.add(job);
    }
  }
}
 return jobList;
 

You will notice that Camundas RuntimeService enables us to query ProcessInstances by processDefinitionKey and ProcessVariables (CustomerId). That gave us a list of matching process instances. So far so good.

We now used this list to extract every active timer job of each instance, using Camundas ManagementService. To ensure to exclusively hold the requested timers in hand (one process instance might include further timers), we needed to compare each timer jobs “name” with the given boundaryEventName. The necessary information can be found in field JobHandlerConfiguration, made available by casting the job to TimerEntity, supplying a matching getter (images 2 and 3).

timerEntity

Image2

 

inspect job

Image3

OK – after we got hands on the requested TimerJobs, we suspended them.

The second step, after a car was ordered was to delete the other, now unimportant, instances:

To delete all the other process instances of cars we aren’t interested anymore, we called this piece of code in the end of a successful process:

public void deleteAllOtherMultibidProcessesOfUser(String processDefinitionKey, Long customerId,
    String instanceIdToStayAlive){
        List<ProcessInstance> processInstanceList =
        runtimeService.createProcessInstanceQuery().processDefinitionKey(processDefinitionKey)
        .variableValueEquals(ProcessVariables.USER_ID, customerId).active().list();

    for (ProcessInstance processInstance : processInstanceList) {
       if (!instanceIdToStayAlive.equals(processInstance.getId())) {
          runtimeService.deleteProcessInstance(processInstance.getId(),
          "Instance deleted because user ordered other car.");
       }
    }
 }

Again, we used

  • CustomerId (to get all instances for)
  • processDefinitionKey (to distinguish from instances of other processes)

while we introduced

  • instanceIdToStayAlive.

This seemed to be the easiest way to make sure not to delete the actual calling instance.

As you can see, we use RuntimeService again to query process instances by ProcessDefinitionKey and CustomerId. After that, we only kept alive the one instance, that was still relevant for handling the customers car-leasing.

I hope this post was useful,

Stefan

 

 

Veröffentlicht unter BPM, camunda BPM, Java | Hinterlasse einen Kommentar

Agile Retreat v3

Am 19.09.2014 trafen sich eine gut gemischte Truppe von knapp 20 Personen (darunter auch erstmals Mitarbeiter unserer Kunden!) zum 3. Agile Retreat von OPITZ CONSULTING im beschaulichen Ebersberg in der Nähe von München. Vom Gesellschafter über Studenten bis hin zu einer Vertreterin aus dem Bereich HR, ihnen allen war eines gemeinsam: Das Interesse an agiler Softwareentwicklung.

001

Nachdem gegen 18 Uhr der Großteil der Teilnehmer seinen Weg durch das verschlafene Oberbayern gefunden hatte und im idyllischen Landgasthaus eingetroffen war, trafen wir uns zu einem ersten Kennenlernen in lockerer Atmosphäre.

In zufälligen Tischgruppen galt es zunächst Fragen zu beantworten. Wichtig dabei: Nur eine Antwort pro Tisch. Also gleich Kopfüber ins Teamwork. Dabei erfuhren wir neben “mit wem wir es zu tun hatten” auch “die schönsten Erlebnisse im Zusammenhang mit agiler Softwareentwicklung” sowie die “größten Lehren” bei eben dieser. Beispielsweise, dass auch bei einem etablierten Scrum-Team in der 16. Retrospektive noch Verbesserungsvorschläge gefunden werden können, die nicht bereits x-Mal thematisiert wurden.

Nachdem nun das erste Eis gebrochen war, ging es zum gemeinsamen Abendessen. Während sich die nicht Heimischen durch die diversen angebotenen Biersorten Bayerns probierten, ging der rege Austausch weiter: Von vergangenen und aktuellen Projekten über Privates bis hin zu alten „Kriegsgeschichten“ der Softwareentwicklung vor vielen Jahren.

Nach einer kurzen Nacht ging es am Samstag dann mit Vollgas ins Tagesprogramm. Nach einem kurzen Impulsvortrag von Christian und Stefan (“Agilität entmystifiziert”), in dem mit den gängigsten Vorurteilen gegenüber Agile aufgeräumt wurde, ging es in Form eines Open Spaces weiter. Somit wurde allen Teilnehmern die Möglichkeit einer aktiven Beteiligung geboten und diese auch intensiv genutzt.

Unter anderem wurden folgende Themen beleuchtet und lebhaft diskutiert:

  • Agil mit kleinen Teams?
  • Don’t call it agile – Was verstehen wir wirklich unter Agilität und was nicht.
  • Agile Softwareentwicklung in vielen (verteilten) Teams.
  • Agile im Softwarecraftmanship?
  • User Stories in der Migration von Legacy Systemen
  • Wie Agilität in neuen Teams einführen?
  • Welche Tools braucht man eigentlich?
  • Agiles Management
  • uvm.

Mit einer vollen Agenda und drei parallelen 30min-Slots für die jeweiligen Themen konnte sich jeder der Gruppe anschließen, die sein Interesse am Meisten weckte oder eben von Board zu Board schlendern und sehen, wo man hängen blieb.

002

So entfachte sich beispielsweise an einem Board eine spannende Diskussion darüber, wie es besser gelingen kann Entscheider auf Managementebene vom Vorteil agiler SW zu überzeugen und wie viel Controlling in einer agilen Welt möglich und vielleicht auch notwendig ist.

Bei einer weiteren Gruppe ging es um die Frage, ob und wie man Prinzipien aus der agilen Welt auch zur Weiterbildung von Mitarbeitern nutzen kann. Ein Werkstudent stellte in diesem Zusammenhang seine fast fertige Bachelorarbeit zum Thema vor.

Stefan berichtete über seine eigenen Erfahrungen wie Scrum auch im Großen funktionieren kann. Während vielen von uns der Kopf schwirrte, bei der Vorstellung mehr als 10 abhängige Scrumteams zu koordinieren, erzählte er voll Begeisterung seinen eigenen Lernprozess, von Scrum Master Runden, Review Messe und wir lernten den Begriff des “Termin-Tetris”!

Über seine Erfahrungen mit agilem Management berichtete Harald und gab darüber hinaus eine Reihe von Literaturempfehlungen. Die Diskussion über das Thema brachte dann auch noch die Erkenntnis mit sich, dass vor allem ein aktives Vorleben der Prinzipien des agilen Managements wichtig ist.

Nach dem Mittagessen mit guter bayerischer Kost half gegen das Suppen-Koma nur noch spielen. Während sich eine Gruppe angeleitet durch Christian via Kanban-Brettspiel (http://getkanban.com/) dem vorher in einer weiteren Session von Harald kurz vorgestellten Thema Kanban spielerisch weiter näherte, erhielt die zweite Gruppe mit Hilfe von jeder Menge Legosteinen eine tolle Methodik zum Einsatz in Retrospektiven vorgestellt.

003

Zum Abschluss des Open Spaces und des gesamten Agile Retreats stand die Zusammenfassung der einzelnen Themen und Erkenntnisse. So durchlebten wir kurzweilig noch einmal die einzelnen Stationen des Tages, vor allem die, an denen wir nicht teilnehmen konnten. Oft mussten wir uns auf die Zunge beißen das ein oder andere Thema nicht direkt wieder aufzunehmen.

Nach einem ereignisreichen (halben) Wochenende ging es nun wieder nach Hause. Viele Themen wurden angesprochen und diskutiert. Viele Anregungen mit auf den Weg gegeben. Aber vor allem haben sich hier in Oberndorf motivierte und engagierte Leute zusammengefunden, die mit Feuereifer dabei sind, nach immer besseren Lösungen zu suchen und diese Erfahrung bereitwillig mit anderen teilen möchten.

004

Auch für 2015 sind wir uns sicher, wieder einen Agile Retreat durchführen zu wollen. Denn wie wir gelernt haben: Auch in der 16. Retrospektive gibt es noch neue Erkenntnisse.

Veröffentlicht unter Agile | Verschlagwortet mit , , , | Hinterlasse einen Kommentar

Patch SOA/BPM VM to WebCenter 11.1.1.8

At http://www.oracle.com/technetwork/middleware/soasuite/learnmore/vmsoa-172279.html one can find the latest 11g SOA/BPM Virtual Machine (VM) which also contains Webcenter. Unfortunately, Webcenter has been added in version 11.1.1.7 to that VM; as there are major enhancements in Webcenter 11.1.1.8 it generally makes sense to upgrade the VM to that version.

At http://docs.oracle.com/cd/E29542_01/doc.1111/e16793/patch_webcenter.htm#BABGAFDE a documentation for upgrading from 11.1.1.7 to 11.1.1.8 can be found. In this post I want to describe which steps of the update guide I actually executed in order to upgrade my VM and which ones I skipped as they seem to be optional.

The particular steps are also described in full detail here:

http://docs.oracle.com/cd/E29542_01/doc.1111/e16793/patch_webcenter.htm#CCHJFGDG

 

Pre-Patching Tasks

I skipped all pre-patching tasks, as we’re starting with a VM that does not contain any data so far and which already contains an up to date Weblogic installation.

 

Installer for WC Portal and WC Content

The installers for upgrading WC Portal and WC Content can be downloaded from the Oracle support page at support.oracle.com using the following patch ID’s:

17068143 (WC Portal)

17068216 (WC Content)

Just start the VM and run the installer scripts (when asked for a JDK/JRE location, enter “/oracle/javahome/jdk1.6.0_45/jre”), first the one for WC Portal, followed by the one for WC Content. When asked for it within the installation, skip software updates. Apart from that generally use the installer’s default values.

I skipped the Oracle SES installation, as the feature isn’t required for training and/or proof of concept matters.

 

Applying the Patch Set

Additional information can be found here:

http://docs.oracle.com/cd/E29542_01/doc.1111/e16793/patch_set_assistant.htm#BABEBGEJ

The schema check performed on the initial DB was successful (query SELECT OWNER, VERSION, STATUS, UPGRADED FROM SCHEMA_VERSION_REGISTRY), so you can skip this step.

The psa script needed to start the patch set assistant can be found at “/oracle/fmwhome/oracle_common/bin”.

I didn’t upgrade all schemas, just the following ones:

  • WEBCENTER
  • DISCUSSIONS
  • DISCUSSIONS_CRAWLER
  • OCS
  • OCSSEARCH

The first three schemas are for WC Portal, the last two for WC Content. The other schemas for those two applications couldn’t be updated successfully (e.g. ACTIVITIES, this schema seems to not exist on the VM so it obviously can’t be updated) but so far I didn’t encounter any problems when working with the VM.

Use the following database credentials:

  • Connection: “localhost:1521″
  • User “sys as sysdba”
  • Password “welcome1″

NOTE: for the OCSSEARCH schema you must add the prefix “DEV_” to the schema name when trying to connect to the DB in the wizard.

 

Post-Patching Tasks

The Webcenter permissions definitely need to be updated. Otherwise, both the PortalBuilder and the administration pages in WC Portal can not be opened.

Detailed information can be found here:

http://docs.oracle.com/cd/E29542_01/doc.1111/e16793/patch_webcenter.htm#CCHFIIDI

The wlst.sh can be found at “/oracle/fmwhome/wlserver_10.3/common/bin”.

 

Now the VM should be successfully updated to Webcenter 11.1.1.8.

I would recommend to directly apply the latest patches for both WC products which can be downloaded from the Oracle support page at support.oracle.com. We used the following Patch ID’s when this blog post was created:

19194669 (WC Portal 11.1.1.8.5)

19334406(WC Content 11.1.1.8.7)

The WC Portal patch contains the “NewAssetBP3.zip” file. To use the assets (new templates and skins), unzip the folder and upload the ear files to the portal using the SharedAssets section in the portal administration.

 

Having executed all of these steps the VM should contain Webcenter Portal and Content in the latest version of 11.1.1.8. If you encounter any problems when working with WC Portal and/or Content on the VM then please let us know.

Veröffentlicht unter Webcenter | Verschlagwortet mit , , , , | Ein Kommentar

BPM / SOA 12c: Re-configure a compact domain to use a DB-based MDS instead of a File-based MDS

Posted by: Sven Bernhardt, Danilo Schmiedel

The Oracle SOA Suite and Oracle Business Process Management Suite offers different domain configuration types applicable for different use cases. For details check out the two guides: Installing SOA Suite and Business Process Management Suite Quick Start for Developers as well as Installing and Configuring Oracle SOA Suite and Business Process Management.

Default Domain Standalone Domain Compact Domain Full Domain
Description Integrated WebLogic Server from JDeveloper Standalone Admin Server with SOA/BPM Standalone Admin Server with SOA/BPM Full installation with separate servers for SOA, OSB, BAM, Admin Server, etc.
Installed via Quick Start distribution Quick Start distribution Quick Start distribution FMW 12c Infrastructure +
FMW 12c SOA Suite and Business Process Management
Used for Local development and debugging, especially for demos or evaluation purposes Local development and debugging, especially for developers who want to use the Oracle Service Bus Design Time Console instead of JDeveloper Local development with SOA components that are incompatible with JavaDB (ESS, MFT, B2B, Heathcare, BAM, ACM API) All stages Development (shared), Integration, Test, Production
Repository Pre-configured Java DB Pre-configured Java DB Oracle Database (please note that MDS and OWSM are file-based) Oracle Database

For all of the domain options which are installed via quickstart distributions, SOA and B2B use the MDS file system. This means that the edit function in SOA Composer is not supported and so Business Rules and Domain Value Maps cannot be changed during runtime & without a new deployment . For the development in our projects we very often use the compact domain. The change of business rules without re-deployment is quite important for us because we work a lot with Adaptive Case Management – and there Business Rules and live changes without re-deployment are a key benefit (which we also like to show in demos / POCs / etc.).

This post concentrates on the compact domain and its re-configuration of the underlying MDS setup, so that a DB-based repository is used instead of a File-based one. After going through the steps below it should be possible to edit rules and DVMs during runtime.

Please note: 
The following steps should only be applied to a fresh & clean compact domain without any composite deployments and instance data. The following approach is not documented in the Oracle documentation, which means that it is not officially supported.

 

Approach

 
  • Start WLST (\soa\common\bin) and connect via WLSTconnect
    'weblogic','welcome1','t3://localhost:7001'
  • Export current content of SOA-MDS (file-based MDS)
    exportMetadata(application='soa-infra', 
        server='AdminServer',
        toLocation='[YOUR-EXPORT-DIR]', docs='/**')
  • Shutdown soa-infra via WLS Console
  • Deregister the file-based MDS
    • Open EM and right-click your domain under Weblogic Domain > Other Services > Metadata Repositories
    • Select mds-soa under “File-Based Repositories” and click on Deregister
    • Please note: If you try to deregister from another page or context, you’ll receive the following error message:
      The selected repository mds-soa cannot be deregistered from within the context of itself. Select domain node from the navigation tree and deregister the repository from the Metadata Repositories page.
  • Register a new DB-based Repository
    • Delete existing mds-soa datasource before from WLS Console > Data Sources
    • Open EM and right-click your domain under Weblogic Domain > Other Services > Metadata Repositories and select Register under “Database-Based Repositories”
    • Enter the connection details appropriate to your MDS-schema

Register_MDS-SOA_12c

  • Create a new Repository Partition and name it soa-infra

Create_partition_soa-infra_12c

  • Use WLST to import exported metadata into the new MDS-Partition
    importMetadata(application='soa-infra', server='AdminServer', fromLocation='[YOUR-EXPORT-DIR]', docs='/**')
  • Restart the server

Post-Start checks

 
After the server restart, you should do the following checks, to ensure that the applied configuration has been applied correctly.
 
  • Check connection between soa-infra application and the new metadata repository (MDS-SOA, Right-click EM Domain Home -> Other Services ->
    Metadata Repositories > soa-infra > Applications)


Applications_using_soa-infra_partition_12c

  • Open BPM Composer and check if any errors are displayed when using it
  • Check SOA Composer for having “Create Session” Button


SOA_Composer_12c

 

If these tests are successful: Congratulations! Your domain is ready to use a DB-based MDS repository for soa-mds.

Veröffentlicht unter Oracle BPM Suite, Oracle FMW, Oracle SOA Suite | Verschlagwortet mit , , , | Hinterlasse einen Kommentar

Analyse der Software-Qualität mit SonarQube

Was ist SonarQube?

SonarQube ist ein Werkzeug, das mittels statischer Code-Analyse technische Qualitätsmerkmale von Software erfasst und diese in einer übersichtlichen Oberfläche darstellt. Neben der Analyse von Java-Quellcode können mittels diverser Plugins auch JavaScript, Groovy, PHP, C# und viele weitere Sprachen analysiert werden. Die offizielle SonarQube Seite listet die verfügbaren Plugins auf. In diesem Artikel beschränke ich mich auf die Analyse von Java-Projekten mittels SonarQube.

SonarQube besteht aus den drei folgenden Komponenten:

  1. Das Analyse-Modul untersucht den Quellcode. Zum Aufruf der Analyse existieren Plugins für Apache Maven und Apache Ant. Zusätzlich existiert ein eigenständiger SonarQube-Runner. Mittels dieser Tools kann die Quellcode-Analyse innerhalb des Builds (beispielsweise in einem CI-System) automatisiert aufgerufen werden.
  2. Die Analyse-Ergebnisse werden in einer Datenbank gespeichert, so dass diese im Nachhinein ausgewertet werden können. Dabei wird neben den jeweils neusten Analyse-Ergebnissen auch eine Historie gespeichert, sodass untersucht werden kann, wie sich die Qualitätsmerkmale im Laufe der Zeit ändern. SonarQube kann mit diversen relationalen Datenbanken betrieben werden.
  3. Eine Webanwendung, mittels der die Analyse-Ergebnisse betrachtet werden können. Die einzelnen Ergebnisse werden zunächst übersichtlich innerhalb eines konfigurierbaren Dashboards angezeigt. Von dieser Übersicht kann man über eine Drill-Down-Funktion weitere Details anzeigen lassen.

SonarQube analysiert den Programm-Code hinsichtlich der folgenden Qualitätsbereiche (Quelle sonarqube.org) :

  • Softwarearchitektur & Softwaredesign
  • Duplikation
  • Unit tests
  • Komplexität
  • Potenzielle Fehler
  • Quellcode-Richtlinien
  • Kommentare

Intern verwendet SonarQube die folgenden Werkzeuge für die Analyse:

  • In SonarQube 4.4 existieren noch Rules, welche die Tools Checkstyle, PMD, Findbugs verwenden. Diese Rules werden von dem Hersteller nach und nach abgelöst durch Regeln, welche mit einer SonarQube eigenen Rules-Engine geprüft werden. (Details: SonarQube Blog)
  • Darüber hinaus werden auch Analyse-Ergebnisse von diversen Tools zur Ermittlung der Testabdeckung eingelesen und in der SonarQube Datenbank gespeichert. Diese können ebenfalls in der Webanwendung betrachtet werden.

SonarQube Webanwendung

Einstiegspunkt in eine Analyse innerhalb der Webanwendung ist das Dashboard. Im linken Bereich werden einige Meta-Informationen wie Anzahl an Klassen, Dateien, Methoden etc. dargestellt. Rechts finden sich die Ergebnisse der Regel-Überprüfungen, direkt darunter Metriken bzgl. der Abhängigkeiten zwischen Dateien.

01_dashboard

In der Ansicht des Dashboards können die Ergebnisse der letzten Analyse mit vorherigen Analysen verglichen werden. So kann schnell erkannt werden, ob sich die Ergebnisse verschlechtern oder verbessern. Auswählbar sind die Änderungen seit der vorherigen Analyse, Unterschiede über die letzten 30 Tage oder Änderungen seit der letzten Version. Die bei der Analyse verwendete Versionsnummer wird bei Maven-Projekten aus dem Version Feld der POM entnommen. Bei anderen Projektarten wird die Versionsnummer bei der Analyse über das Property sonar.projectVersion festgelegt.

In den folgenden Abschnitten werden einige einzelne Analyse-Ergebnisse exemplarisch dargestellt.

Anzeige der Testabdeckung

Im Dashboard werden die Ergebnisse der Testabdeckung angezeigt. Dabei wird unterschieden zwischen Unit- und Integrations-Tests.

02_testabdeckung

Abbildung 1: Anzeige der Testabdeckung eines Projektes

Die Anzeige der Testabdeckung setzt eine korrekte Projekt-Konfiguration voraus. Um bei der Ausführung der Unit- und Integrationstests die Daten zur Testabdeckung aufzeichnen zu können, muss die Java Virtual Maschine entsprechend instrumentiert werden. Hierzu kann z. B. JaCoCo verwendet werden. Eine Beispiel-Konfiguration und Details zum Aufruf der Analyse sind in dem GitHub-Repository sonar-examples von SonarSource  und in der SonarQube Dokumentation (Konfiguration für Unit-Tests, Konfiguration für Integration Tests) zu finden.

Bewertung

Bei dieser Metrik muss stets beachtet werden, dass eine hohe Testabdeckung alleine noch nicht zwangsläufig eine gute Qualität der Software bedeutet. Beispielsweise ist es möglich, “Tests” zu schreiben, die kein einziges Assert-Statement enthalten. Weiterhin müssen Tests natürlich auch fachlich korrekt sein, was selbstverständlich nicht von einer Software überprüft werden kann.

Anzeige der Regelverletzungen

Die Regelverletzungen werden nach ihrem Schweregrad gruppiert. Nach Auswahl eines Schweregrads werden die verletzten Regeln angezeigt.

Das Bespiel zeigt einige Regeln, welche von SonarQube als Kritisch angesehen werden:

03_regelverletzungen

Nach Auswahl einer Klasse wird diese – zusammen mit den Regelverletzungen – im unteren Bereich dargestellt:

04_regelverletzungen

Praktisch ist die gute Navigierbarkeit innerhalb der Anwendung. So ist es möglich, andere Verletzungen innerhalb der gerade angezeigten Klasse anzusehen. Zur Erhöhung der Übersichtlichkeit kann die Klasse auch in einem separaten Fenster geöffnet werden.

Komplexität

SonarQube ermittelt die zyklomatische Komplexität (Mc-Cabe-Metrik) des untersuchten Projektes. Zur Bestimmung der Metrik wird die Anzahl der folgenden Schlüsselwörter je Methode bzw. je Klasse gezählt:

  • if, for, while, case, catch, throw, return (ausgenommen des letzten return-Statements einer Methode), &&, ||, ?

Es sollte generell eine kleine Zahl und damit geringe Komplexität von Methoden angestrebt werden, da angenommen wird, dass eine Methode umso schwerer von Menschen verstanden werden kann, je höher die Zahl ist.

Bewertung

Die Metrik der zyklomatischen Komplexität ist nicht unumstritten. Ein Switch-Statement mit vielen Case-Anweisungen kann z.B. trotz hoher Komplexitäts-Zahl dennoch übersichtlich sein.

Im Dashboard werden die Durchschnittswerte der Komplexität angezeigt:

05_komplexität

Die Gesamtsumme der Komplexität stellt kein Qualitätsmerkmal dar, sondern gibt einen generellen Hinweis auf die Projektgröße. Die Durchschnittswerte der Komplexität je Methode sind alleine nicht sehr aussagekräftig. So wurde im Beispiel ein Projekt gezeigt, in dem unter anderem viele via Hibernate persistierte Domain-Objekte vorhanden sind, welche zumeist einfache Datenhalte-Objekte sind. Diese reduzieren natürlich die durchschnittliche Komplexität. (Laut Martin Fowler sind solche  „blutarmen“ Domain-Modelle eine Anti-Pattern. Siehe auch AnemicDomainModel)

Mittels Klick auf eine der Komplexitätszahlen kann zu der der Detail-Ansicht navigiert werden, in der weiter durch Packages bis hinunter zu den einzelnen Klassen navigiert werden kann.

Hotspots

Um schnell einen Überblick über die Qualität einer Software zu erhalten, eignet sich der Bereich Hotspot.

Beispiele:

  • Hotspot per nicht abgedeckter Quellcodezeilen
  • Hotspot per Komplexität je Klasse
  • Hotspot per Komplexität je Methode
  • Meist verletzte Ressource
  • etc.

Design

Im Dashboard werden mittels der “Package Design”-Komponente Informationen zu Abhängigkeiten zwischen den Packages und zu zirkulären Abhängigkeiten angezeigt:

08_design

Von dort gelangt man durch Klick auf eine Zahl direkt zur “Dependency Structure Matrix“, in der die Abhängigkeiten der Komponenten (d. h. der Java Packages) dargestellt werden. Mit Hilfe dieser Matrix können zirkuläre Abhängigkeiten im Projekt gefunden werden. Gutes Software-Design vermeidet generell zyklische Abhängigkeiten zwischen einzelnen Packages.

09_dsm_design

Das Diagramm enthält für jedes Package je eine Zeile (mit Beschriftung) und ebenfalls eine korrespondiere Spalte. Innerhalb des Diagramms wird dargestellt, wie viele Klassen eines Packages Klassen aus anderen Packages verwenden. Mögliche zirkuläre Abhängigkeiten können an den rot hinterlegten Zahlen im oberen rechten Bereich der Matrix erkannt werden.

Beispiel

Durch Doppelklick auf eine Zahl (im Beispiel rote “1” in der Zeile “vorhaben”) werden unterhalb des Diagramms weitere Details der Abhängigkeiten der beiden Packages vorhaben und imp dargestellt:

09_dsm_design_uses

Welche Klassen aus dem Package imp (links) verwenden welche Klassen aus dem Package vorhaben (rechts)

Weitere Details zur Dependency Structure Matrix sind in der SonarQube Dokumentation auf der Seite Cycles – Dependency Structure Matrix enthalten.

Hinweise für den praktischen Einsatz von SonarQube

Definition von projektspezifischen Qualitätsprofilen

Nachdem die SonarQube Analyse eines größeren Projektes mit langer Historie erstmalig ausgeführt wurde, sind häufig sehr viele Metriken diverser Regeln verletzt. In einem großen Projekt können diese Verletzungen nicht unmittelbar durch entsprechende Änderung im Quellcode behoben werden. Dies ist auch nicht in jedem Projekt sinnvoll und notwendig.

Vor der regelmäßigen Verwendung von SonarQube sollten sich die Entwickler des Projektes daher zunächst auf eine Menge von Regeln einigen, die im Projekt eingehalten werden sollen. Dazu kann auch gehören, dass man die Kritikalität einzelner Regeln entsprechend der konkreten Projekt-Notwendigkeiten erhöht oder verringert.

Für die Konfiguration von solchen projektspezifischen Regeln bietet SonarQube den Einsatz von sogenannten “Quality-Profiles” an. Durch Qualitätsprofile kann festgelegt werden, welche Regeln für die Analyse verwendet werden sollen und mit welcher Kritikalität Regelverletzungen protokoliert werden sollen.

Wird bei der SonarQube-Analyse kein Qualitätsprofil angegeben, verwendet SonarQube per Default das Profil Sonar-Way. Alternativ kann durch Setzen des Properties sonar.profile der Name des gewünschten Profils beim Aufruf der Analyse angegeben werden.

Zur Pflege eines eigenen Profils kann ein bereits vorhandenes Profil kopiert und angepasst werden. Die Anpassung eines Profils wird dabei innerhalb des Bereichs “Rules” der Anwendung vorgenommen:

10_rules

Bei der Auswahl von Regeln sollte auch geprüft werden, ob im verwendeten Profil deaktivierte Regeln (Filter Activation: Inactive setzten!) existieren, welche im Projekt interessant sein könnten.

Unterdrückung von Validierungen

Zur Unterdrückung von Validierungen bietet SonarQube die folgenden Möglichkeiten:

  • Einfügen des Kommentars //NOSONAR am Zeilenende, wodurch die Analyse für diese Zeile komplett verhindert wird.
  • Annotation einer Methode mittels @SuppressWarnings(“all”), um die Analyse der gesamten Methode zu unterbinden.
  • Eine konkreter Validierungsfehler kann auch mittels der Webanwendung als “falsch positiv” deklariert werden:

11_falschpositiv

Anzeige von Änderungen

Bei der Anzeige der Regelverletzung können entweder alle Verletzungen angezeigt werden oder nur das Delta zwischen verschiedenen Analyse-Zeitpunkten. Beispielsweise ist die Anzeige der Veränderung seit der Analyse des letzten Release sinnvoll, um rechtzeitig (z. B. noch vor der Auslieferung eines Releases) erkennen zu können, wenn sich die Qualität (hinsichtlich der Metriken) in der aktuellen Version verschlechtert.

Anzeige aller Verletzungen:

12_aenderungen_1

Anzeige der Veränderungen innerhalb der letzten 30 Tage:

13_aenderungen_2

Bei der Anzeige der Regeln werden allerdings nur die Verschlechterungen in der Delta-Anzeige berücksichtigt. Dieser Umstand kann – je nach Persönlichkeit des Entwicklers – unter Umständen auch demotivierend sein.

Umso schöner und motivierender kann daher die Anzeige der Änderung im Dashboard sein:

14_aenderungen_dashboard

Eine Anzeige des Analyseverlaufs über verschiedene Versionen bietet die Seite “Historisch” (Deutsche Version)  bzw. “Time Machine” (Englische Version):

15_timemachine

Hinweis: Die Integration-Tests des Projektes wurden ohne Erfassung der Testabdeckung ausgeführt.

Quality Gates und das Build-Breaker Plugin

Mittels Quality Gates können Grenzwerte definiert werden, welche im Projekt nicht überschritten werden dürfen. Durch die Verwendung des Build-Breaker Plugins ist es möglich, den Build fehlschlagen zu lassen, wenn die im Quality Gate definierten Anforderungen nicht erfüllt wurden.

Fazit

Mit SonarQube wird und ein reichhaltiges und mächtiges Werkzeug für die Qualitätsanalyse von Software-Projekten an die Hand gegeben. Richtig konfiguriert und eingesetzt, liefert SonarQube Informationen zu Schwachstellen in Software-Projekten, welche für die daraus geleitete Qualitätsverbesserung eingesetzt werden können.

Bei der Verwendung von SonarQube sollte jedoch immer im Auge behalten werden, welches Ziel mit der Analyse erreicht werden soll. Im Projektteam wird man daher über die verschiedenen Metriken und Regeln diskutieren und sich nach der (hoffentlich eingetretenen) Einigung ein eigenes Qualitätsprofil definieren, welches im Zuge des weiteren Projektverlaufs verwendet wird.

Weiterhin führt die Analyse alleine nicht automatisch zu besserer Qualität. So sind nach der Identifizierung von Schwachstellen im Code selbstverständlich entsprechende Refactoring-Maßnahmen notwendig.

Darüber hinaus sollte das manuelle, durch einen Projektteam-Kollegen durchgeführte Quellcode-Review auch trotz SonarQube weiter durchgeführt werden, um auch Qualität hinsichtlich fachlicher Korrektheit und guter Verständlichkeit (bspw. Benennung von Klassen, Methoden und Variablen) sicherstellen zu können.

Veröffentlicht unter Architecture, German, Java, Quality | Hinterlasse einen Kommentar