WS-Security with Username Token Profile on Oracle Weblogic Server

WS-Security Username Token Profile is a simple authentication scheme for SOAP-webservices using username an password sent in the requests‘ WS-Security headers. The password is hashed using a salt and a timestamp (password digest) to prevent replay attacks. It is specified in this document. As this does not involve any message encryption it should not be used without transport encryption.
In this post I will show how I configured this for a webservice to be deployed on a recent Weblogic Server (12.2.1.2).

WS-Policy configuration

On Weblogic webservices security is configured using policy files following WS-Policy standards. The easiest way to secure a webservice is to configure one of the prebuilt policy files shipped with Weblogic, in this case Wssp1.2-2007-Https-UsernameToken-Digest.xml which enforces both authentication and transport level security. How to enable this manually after the service is deployed is described in the Admin Console Online Help.
In my case I just wanted to test authentication without bothering with certificates so I deployed my own policy file which does not enforce the use of transport level encryption:

<wsp:Policy
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
    xmlns:sp="http://docs.oasis-open.org/ws-sx/  ws-securitypolicy/200702">
    <sp:SupportingTokens>
        <wsp:Policy>
            <sp:UsernameToken
                sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
                <wsp:Policy>
                    <sp:HashPassword/>
                    <sp:WssUsernameToken10/>
                </wsp:Policy>
            </sp:UsernameToken>
        </wsp:Policy>
    </sp:SupportingTokens>
</wsp:Policy>

Custom policies are stored under /WEB-INF/policies in the webservice war file. Automatic activation after deployment can be achieved either by use of a deployment plan or by annotating the service implementation class with the weblogic.jws.Policy annotation as described in the Oracle documentation. The downside of this approach is that our code now depends on server-specific libraries but in our case this was the easiest way.

Configuring the security realm

Weblogic uses security realms to manage users and groups for authentication. In our case we used the default realm which is configured when setting up the default admin user. By default this security realm does not support password digest authentication, so we need to enable this using the WLS Admin Console: After selecting our default realm „myrealm“ in the Security Realms overview we change to the Providers-tab.

wls_providers

There we first select the DefaultAthenticator and switch to its Provider Specific-tab. There we check the Enable Password Digest-checkbox and save our changes.

default_authenticator

Back in the myrealm |Providers-tab we now select the DefaultIdentityAsserter. On its Configuration-tab we add wsse:PasswordDigest to the list of active authentication types.

default_asserter

We save our changes and restart Weblogic. As we changed the way Weblogic stores its users‘ passwords we need to reset the passwords of all users we want to access our webservice with.

Testing

In most cases I use SoapUI for manually testing webservices. It supports password digest authentication but unfortunately at least the version I used seems to add a binary nonce to the SOAP-header which Weblogic cannot understand. I therefore built a Java-Client using only standard JDK-features following the description in this blog post.

Wrapping it up

To configure a webservice to use authentication following the WS-Security Username Token Profile we need to add a corresponding WS-Policy file. To make password-digest-authentication work we also need to configure our security realm to support this feature. Testing a webservice using password-digest-authentication might be a little inconvenient depending on the tools you use.

Veröffentlicht unter BPM & System Integration | Kommentar hinterlassen

Machine Learning for Optimizing Containerstorage

595px-Container_Augsburg

Von Eigenes Werk, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=1923693

Consider the following setup. You provide space to store containers and your customers have, after bringing the containers to you, the flexibility to retrieve them whenever they like. In order to not waste space you stack containers onto each other leaving you with a fundamental question: which container should be on top and which at the bottom? It is clear that you want „fast“ containers, i.e. containers that will probably be retrieved in near future, should not be stored under a „slow“ container, because then you will have to rearrange the containers in order to get access to the fast one. The key question hence is, how to find out in advance, which containers will be slow and fast.

Weiterlesen

Veröffentlicht unter Analytics & BigData | Verschlagwortet mit , , | Kommentar hinterlassen

Testing Angular components using MdDialog

When testing a component that dynamically opened a dialog using Angular Material (2), I was getting an error I didn’t immediately expect. The MdDialogModule was added to the imports, so my TestBed knew what was going on but my dynamically loaded Component caused problems.

Error: Error in ./AdminHomeComponent class AdminHomeComponent – inline template:21:24 caused by: No component factory found for OfferFormDialogComponent. Did you add it to @NgModule.entryComponents?

Okay, researching the problem online gave me an issue on Github for the angular repository. It suggested the following in the beforeEach block:

 

TestBed.overrideModule(BrowserDynamicTestingModule, {
    set: {
        entryComponents: [OfferFormDialogComponent],
    },
});

Sure, this solved the problem but it then causes an actual dialog to be opened during our tests. Well I really just want to test if the framework class gets called. I don’t want to test if the framework actually does what it promises.

Screen Shot 2017-03-21 at 17.46.10

The tests and the created but uninvited dialog

It turns out, the solution is much cleaner, if you just mock instead of actually calling the MDDialog method.

So instead of

spyOn(component.dialog, 'open').and.callThrough();

we do

let mockDialogRef = new MdDialogRef(new OverlayRef(null,null,null,null),{});
mockDialogRef.componentInstance = new OfferFormDialogComponent(null, null);
spyOn(component.dialog, 'open').and.returnValue(mockDialogRef);

and later in the test spec

it('should open the dialog on clicking the button', fakeAsync(() =&amp;gt; {
        expect(component.dialog.open).toHaveBeenCalledTimes(0);
        clickAddNewButton(component, fixture);
        fixture.detectChanges();
        tick();
        expect(component.dialog.open).toHaveBeenCalled();
}));

This way, a clean test of the component without too many dependency is possible. Yes, I am creating a new instance of my OfferFormDialogComponent, but since its constructor doesn’t do anything anyways, and its not active itself, it’s OK.

The whole test and class can be found on github/gist
Tests
Component

Veröffentlicht unter Uncategorized | Kommentar hinterlassen

Visual Feedback Service for angular http calls v2

TL;DR: A Service for hooking into the xhr events of all http calls. Use it to make spinners spin, turkeys dance or whatever floats your boat while your app fetches data and the user needs to know.


So I started writing a feedback service for angular’s http calls. The idea is simple. When my app does http calls, I want my spinner to spin!

Now you don’t want to constantly set a ‘loading’ flag in your components somewhere or manually show loading overlays all the time right? All you want is a small spinner in the top right that spins on activity. Maybe you also want a toast or some notification to be shown on completed transactions.

I started building this and wrote about it in this blog post, so if you want to read the full story, read that one first.

Version 2: Pulling the UI feedback code out of the API Service

In my previous post, you had to call the vFeedbackService from somewhere when you did an http call and pass it the observable. That was ugly! Sure you could get spinners and toasts in 2 lines of code, but you want 0 lines of code in your components! Just a spinner, is that too much to ask?

So new plan:

  1. Hook into the code that angular uses to make HTTP calls. Grab those events!
  2. Create an observable based on those events. Use it to notify spinner components of stuff going on
  3. Write a spinner component that hooks into this and spins every time when HTTP calls are going on. All other code is untouched

Digging through the Angular code

If you don’t care about this, just skip below to the solution.

Digging into the http code of Angular 2, it becomes clear how it works and what to do. Http uses a ConnectionBackend which is used to create a connection. This connection is created using BrowserXhr.build() (in the browser). So if we wrap this, returning the original object (XMLHttpRequest) but hooking into its events, we’re good. We get all http requests and their open, load, error, abort and progress events.

Creating the new Service to subscribe to

To hook into the events, we override the build() method of BrowserXhr to ensure we grab the events before handing back the original object.

//imports ...

export class CustomBrowserXhr extends BrowserXhr {

    private _observable: Observable<XhrEvent>;
    private _subscriber: Subscriber<XhrEvent>;

    constructor() {
        super();
        this._observable = Observable.create(subscriber => {
            this._subscriber = subscriber;
        }).share();
    }

    get observable(): Observable<XhrEvent> {
        return this._observable;
    }

    build(): any {
        let xhr = super.build();
        if (!this._subscriber) return xhr;

        //at the beginning, we create an event that notifies an opening of a connection
        this._subscriber.next({type: 'open', event: {}});

        xhr.onprogress = (event) => {
            this._subscriber.next({type: 'progress', event: event});
        };
        xhr.onload = (event) => {
            this._subscriber.next({type: 'load', event: event});
        };
        xhr.onerror = (event) => {
            this._subscriber.next({type: 'error', event: event});
        };
        xhr.onabort = (event) => {
            this._subscriber.next({type: 'abort', event: event});
        };

        return xhr;
    }

}

Now, we have something to subscribe to.

To ensure this is actually used, we of course also need to override the default BrowserXhr

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        //...
        CustomBrowserXhr // <<<
    ],
    providers: [{provide: BrowserXhr, useExisting: CustomBrowserXhr}], //!!! <<<
    bootstrap: [AppComponent]
})

Now, we have successfully wrapped an angular internal injectable with our code!

Let’s build a spinner (I am using angular material) that shows on ongoing http events and hides when they are all completed/aborted/cancelled or otherwise closed

@Component({
    selector: 'steak-working-spinner',
    template: `<md-progress-spinner mode="indeterminate" *ngIf="_visible"></md-progress-spinner>`,
    styleUrls: ['working-spinner.component.scss']
})
export class WorkingSpinnerComponent implements OnInit, OnDestroy {

    private _visible: boolean;
    private _subscription: AnonymousSubscription;
    private _connectionCounter = 0;

    constructor(public browserXhr: CustomBrowserXhr) {
    }

    ngOnInit() {
        this._subscription = this.browserXhr.observable.subscribe(next => {
            console.log(next.type + ' next received in spinner');
            switch (next.type) {
                case 'open':
                    this._connectionCounter++;
                    break;
                case 'load':
                    this._connectionCounter--;
                    break;
                case 'abort':
                    this._connectionCounter--;
                    break;
                case 'error':
                    this._connectionCounter--;
                    break;
            }
            this._visible = this._connectionCounter > 0; //if larger 0, its visible! otherwise hide us
        });
    }

    ngOnDestroy(): void {
        if (!this._subscription) return;
        this._subscription.unsubscribe();
        this._subscription = null;
    }

}

This can now be placed anywhere in the app, as often as you want and whereever a process should be indicated. It can also be any UI, all it needs is react to the events of the http calls.

The code above also ensures, the spinner only stops spinning on all http calls being finished. This is helpful, if users quickly perform calls or if they click once but this triggers 2+ http calls.

The resulting UI

Untitled.mov

If you like this, maybe you can help: I have built this and would like to share it. But I am unsure how to ‘correctly’ publish it as an npm module for others to just import and use.

Veröffentlicht unter Uncategorized | 1 Kommentar

Building a visual feedback service for angular http calls with material

Update: I improved this here. Read on for educational purposes, but make sure to read the article linked as well since it makes the whole code prettier and more architecturally neat.

Building web applications using angular is fun, we all know that. With angular material, it’s also pretty to look at. So let’s build a service that gives us some convenience regarding visual feedback for users while performing http requests.

Angular Material has a cool progress spinner component and it also includes toasty notifications that pop from the bottom which they call snack bar.

When performing simple CRUD operations on an arbitrary data structure, wouldn’t it be nice to give a generic feedback system that can be used while developing? Every time we have an http request, it gives feedback, in the form of a progress spinner and optionally also with these little pop up notifications that tell us if everything went right or if problems occurred.

Plan with tests and implement

We need a service that wraps the MdSnackBar Service provided by the MaterialModule. This service can then also manage any spinner components that can register as a listener to this service and get notifications of any ongoing http calls so that they show visual feedback using the spinner. So we create these two:

  • VFeedbackService
  • WorkingSpinnerComponent

First let’s look at the VFeedbackService or rather its spec since we do this test driven:

let snackSpy = jasmine.createSpyObj('snackBar', ['open']);

//...
//....beforeEach, TestBed configurations etc
//...

it('should let listeners subscribe', function () {
        expect(service._listeners.length).toBe(0);
        service.addListener({
            onLoading: () => {
            }, onLoadingComplete: () => {
            }
        });
        expect(service._listeners.length).toBe(1);
    });

    it('should remove listeners on removal', function () {
        expect(service._listeners.length).toBe(0);
        let listener = {
            onLoading: () => {
            }, onLoadingComplete: () => {
            }
        };
        service.addListener(listener);
        service.addListener(listener);
        service.addListener(listener);
        expect(service._listeners.length).toBe(3);
        service.removeListener(listener);
        expect(service._listeners.length).toBe(0);
    });

    it('should notify spinners of processing events and completion', fakeAsync(() => {

        let listenerSpy = jasmine.createSpyObj('listenerSpy', ['onLoading', 'onLoadingComplete']);
        service.addListener(listenerSpy);

        let obs = new Observable(subscribe => {
            subscribe.next('foobar');
            subscribe.complete();
        });
        service.spinUntilCompleted(obs);
        //wait one async cycle
        tick();
        expect(listenerSpy.onLoading).toHaveBeenCalledTimes(1);

        expect(listenerSpy.onLoadingComplete).toHaveBeenCalledTimes(1);

    }));

    it('should not notify spinners if observable has not been completed', fakeAsync(() => {
        let listenerSpy = jasmine.createSpyObj('listenerSpy', ['onLoading', 'onLoadingComplete']);
        service.addListener(listenerSpy);

        let obs = new Observable(subscribe => {
            subscribe.next('foobar');
        });
        service.spinUntilCompleted(obs);
        //wait one async cycle
        tick();
        expect(listenerSpy.onLoadingComplete).toHaveBeenCalledTimes(0);
    }));

    it('should call MdSnackBar on successful response from observable', done => {
        service.showMessageOnAnswer('hooray!', null, new Observable(sub => {
            sub.next('fake server response');
            sub.complete();
        }))
        //inside observable subscription of service
            .subscribe(next => {
                expect(snackSpy.open).toHaveBeenCalledWith('hooray!', undefined, {duration: 1500})
            }, null, done);
    });

    it('should call MdSnackBar  with error on failed response from observable', done => {
        service.showMessageOnAnswer('hooray!', 'fail :(', new Observable(sub => {
            sub.error();
            sub.complete();
        }))
        //inside observable subscription of service
            .subscribe(next => {
                expect(snackSpy.open).toHaveBeenCalledWith('fail :(', undefined, {duration: 1500});
            }, null, done);
    });

 

As is visible from the specs, the service manages a list of listeners and offers http services to hand over their observables so that the service gives feedback once they succeeded or failed.

The tests use angulars async helper functions to properly test all the observables and such. They mock away the SnackBar service as well as any listener components that subscribe to the service

Now that we have the spec, we can simply implement the service. It’s straight forward from the specs but I’ll share it anyways

import {Injectable} from "@angular/core";
import {MdSnackBar, MdSnackBarRef, SimpleSnackBar} from "@angular/material";
import {Observable} from "rxjs";
import {LoadingEventListener} from "./LoadingEventListener";

@Injectable()
export class VFeedbackService {

    _listeners: LoadingEventListener[] = [];

    constructor(private snackBar: MdSnackBar) {

    }

    public addListener(listener: any) {
        this._listeners.push(listener);
    }

    public removeListener(listener: any) {
        this._listeners = this._listeners.filter(item => item !== listener)
    }

    /**
     *
     * @param forthis: The observable to watch and spin for
     */
    public spinUntilCompleted(forthis: Observable<any>): void {
        //start up all listeners
        this.triggerAllListeners();
        //on end of observable call complete for all listeners
        forthis.subscribe(null, null, () => {
            this.completeAllListeners()
        })

    }

    /**
     *
     * @param successMessage
     * @param failMessage
     * @param observableRequest
     * @param actionText
     */
    public showMessageOnAnswer(successMessage: string, failMessage: string, observableRequest: Observable<any>, actionText?: string): Observable<MdSnackBarRef<SimpleSnackBar>> {
        let obs = new Observable(sub => {
            observableRequest
                .subscribe(
                    null,
                    err => {
                        let snack = this.snackBar.open(failMessage, null, {duration: 1500});
                        sub.next(snack);
                        sub.complete()
                    },
                    () => {
                        sub.next(this.snackBar.open(successMessage, actionText, {duration: 1500}));
                        sub.complete()
                    })
        }).publish();
        obs.connect();
        return obs;
    }

    private triggerAllListeners() {
        this._listeners.forEach((listener) => {
            if (listener) listener.onLoading();
        });
    }

    private completeAllListeners() {
        this._listeners.forEach(listener => {
            if(listener)listener.onLoadingComplete();
        });
    }

}

 

This service is not yet perfect. If you have several http requests running in parallel, the first one that completes stops all listeners and therefore stops them from spinning. This can be averted by keeping track of the number of calls to spinUntilCompleted and only notify all listeners of a stop, once all subscriptions are completed. Feel free to add that to your code if you have the need for it.

Now let’s look at the spinner components. They are so simple, writing tests for them is almost not worth it. I skipped it.

import {Component, OnInit, OnDestroy} from "@angular/core";
import {LoadingEventListener} from "../../services/LoadingEventListener";
import {VFeedbackService} from "../../services/vfeedback.service";
import {_keyValueDiffersFactory} from "@angular/core/src/application_module";

@Component({
    selector: 'app-working-spinner',
    template: `<md-progress-spinner mode="indeterminate" *ngIf="_visible">`,
    styleUrls: ['working-spinner.component.scss']
})
export class WorkingSpinnerComponent extends LoadingEventListener implements OnInit, OnDestroy {

    private _visible: boolean;

    constructor(public vfeedbackService: VFeedbackService) {
        super();
    }

    onLoading() {
        this._visible = true;
    }

    onLoadingComplete() {
        this._visible = false;
    }

    ngOnInit() {
        this.vfeedbackService.addListener(this);
    }

    ngOnDestroy(): void {
        this.vfeedbackService.removeListener(this);
    }
}

Using it in our services

public orderPost(offerId: string, takeaway: boolean): Observable<Order> {

        //http call prep code ...
        //...

        let obs = this.http.post(path, orderBooking, requestOptions)
            .map((response: Response) => {
                if (response.status === 204) {
                    return undefined;
                } else {
                    return response.json();
                }
            })
            .publish(); //ensuring we only have one subscription to pass around, otherwise you get multiple http calls every time
        obs.connect();  

        //here we tell the feedback service what we want. we'd like spinning and toasting
        this.vfeedback.showMessageOnAnswer('Order placed!', 'Oops', obs);
        this.vfeedback.spinUntilCompleted(obs);
        return obs;

    }

As you can see, we just create an http call and then pass it to our service so it can hook into the event process. If we only want spinners, we just use spinUntilCompleted, if we also want a message, we call both methods.

It’s important to note here that failing to ensure you are working with a single subscription (using .share() or .publish() ), the VFeedbackService triggers a secondary http call by subscribing to your observable. So be sure to keep that in mind.

Next steps

Next, it would be nice to hook into the http calls event system to automate the spinner and clean this code out of our services. The http service doesn’t care about the visual feedback, it just does what it has to do. But our spinner should be able to know when http calls are performed and act upon it.

Option A: Wrap http and use the wrapping service instead of http directly. A similar approach has been chosen by Auth0, to attach a jwt token to every http request to ensure its authenticated.

Option B: Hook into the stuff that angulars http uses behind the scences, namely BrowserXhr. I will investigate this in a future post.

Wrapping it up

I showed how to create a service that can quickly be used to allow for user feedback using angular material in angular 2 projects. You can replace my component using an md-progress-spinner by a dancing chicken or whatever you please. Hooking into the BrowserXhr will be explained in a follow up post, once I got the code clean and put a bow tie on it.

Veröffentlicht unter Software Engineering | Kommentar hinterlassen

Usability-Rezept für glückliche Chatbots à la Amazon Alexa, Google Home, Apple Siri & Co

Wer versucht, die Gestaltung grafischer Oberflächen eins zu eins auf sog. Conversational UIs (Chatbots, Spracheingaben, usw.) zu bringen, merkt schnell, dass diese Rezepte hier nicht greifen. Es müssen stattdessen neue Zutaten hinzugefügt, alte Muster angepasst und einige Zutaten komplett ausgetauscht werden.

In diesem Artikel finden sich 3 Zutaten, die Spracheingabe und -ausgabe mit Alexa, Siri, Cortana & Co zu einem Genuss und echtem Mehrwert verhelfen können.

Denn gerade das lästige Eintippen von Texten auf kleinen Smartphones macht die Benutzererfahrung von eigentlich guten Applikationen häufig zu einer unangenehmen Sache. Nicht immer sind Sprachbefehle oder gesprochene Antworten die Lösung. Aber in Verbindung mit grafischen Oberflächen lässt sich die Usability deutlich verbessern. Und wer weiß. Vielleicht nutzen wir bald noch ganz andere Interaktionsmöglichkeiten, an die wir bis her noch (sic!) nicht denken.

Veröffentlicht unter IoT & Industry 4.0, Strategy & Methods | Verschlagwortet mit , , , | Kommentar hinterlassen

Co-Creation im Workshop: Anstrengend ergebnisreich.

Unser Workshop war anstrengend … warum eigentlich?

Am 2./3. März verbrachten wir zwei intensive Workshoptage in Nochen: Ein Teil der OC Community (insgesamt 17 Personen) entwickelte Workshopkonzepte und Ideen rund um die Themen Innovation & Digitalisierung, New IT & IT Strategy sowie (Digital) Change. Am Freitag Abend waren wir – was die Gesamtsumme der Endergebnisse anging – eigentlich sehr zufrieden.

Eigentlich. Denn die beiden Workshoptage waren harte Arbeit, unsere Diskussionen waren zum Teil kontrovers-verwirrend-intensiv und auch kräftezehrend. Wir hatten Spaß beim Arbeiten, keine Frage!  Doch manche hatten das Gefühl, dass wir zwischendurch unseren roten Faden verloren hätten, dass wir unsere Ergebnisse als Gruppe homogener und effizienter hätten erarbeiten können. Irgendwie blieb der Eindruck von einem „echt anstrengenden Entscheidungsfindungsprozess“ hängen – trotz des konstruktiven Workshopklimas, des positiven Miteinanders und des guten Gesamtergebnisses.

In den letzten Tagen habe ich gegrübelt, woran das liegen könnte (als Moderator überlegt man ja immer, was man bei der Workshopbegleitung hätte verbessern könnte) … Waren die Workshop-Vorbereitungen nicht gut genug? Hätten wir inhaltlich vorarbeiten müssen, um schneller und effizienter in der großen Gruppe entscheiden zu können? Oder hätten wir uns weniger Themen vornehmen sollen? War der Teilnehmerkreis zu groß oder nicht gut ausgewählt? Hätten wir die Moderation straffer durchziehen müssen, mehr auf die Einhaltung von durchgängiger Anwesenheit und Timeboxes achten müssen?

Erkenntnis #1: Co-Creation in Reinform

Beim Blick zurück auf dem Teilnehmerkreis wurde mir nochmals bewusst, dass wir an beiden Workshoptagen wirklich crossfunktional-interdisziplinär aufgestellt waren: Vom Geschäftsführer über das mittlere Management und (Senior) Beratern bis zum (Noch)Studenten waren nahezu alle Hierarchiestufen unseres Unternehmens vertreten. Beteiligt waren Mitarbeiter aus dem Consulting (Architekten, Developer, Strategieberater und Change Facilitatoren), Marketing, Sales, Business Development und das Kompetenzmanagement. Wie bei der Workshopplanung erhofft (und wie es Workshopgurus und Facilitatoren so oft predigen) trat eine bunt gemischte Teilnehmergruppe an. Diese vielfältigen und zum Teil auch kontroversen Ideen und Meinungen unter einen Hut zu bringen, um in definierten Zeitboxen gute Ergebnisse zu erzielen, ist – ganz simpel – HARTE ARBEIT. Und zwar nicht nur für den Moderator des Workshops. Sondern für alle Teilnehmer. Alles gut also! Aber warum dann dieser vermeintliche „emotionale Workshop-Hangover“ im Nachgang?

Erkenntnis #2: „groan zone emotions“ waren zu Gast!

Vorgestern blätterte ich – einmal mehr – durch Sam Kaners Buch „Facilitator’s Guide to Participatory Decision-Making“ (ein Facilitator-Klassiker aus dem Jahr 2007). Der dort erläuterte „Diamond of Participatory Decision-Making“ beschreibt genau diese „groan zone“, die wir gemeinsam an diesen beiden Workshoptagen (mehrmals) durchlaufen haben:

Neue Datei 2017-03-15 08.35.48_1

Nach der Phase des „divergent thinking“ – Ideen werden frei gesammelt, die Diskussion öffnet sich, verschiedene Sichtweisen treffen aufeinander – folgt die „groan zone“ (der Wendepunkt), ehe die Workshopgruppe über das „convergent thinking“ – Sortierung, Fokussierung, Priorisierung – zur Entscheidungsfindung kommt. In jeder Phase des Workshops, bei jeder Themenerarbeitung, bei jeder Entscheidungsfindung in der Gruppe spielen – mehr oder weniger bewusst und individuell unterschiedlich erlebt – Emotionen eine große Rolle. Das ist einfach menschlich.

Deshalb war es für mich als Moderator im Nachgang des Workshops wichtig, mir – wieder einmal – in Erinnerung zu rufen: Neben den positiven Emotionen (aus den Phasen des divergent /convergent thinking), gehören die „groan zone emotions“ schlicht ebenfalls zu jedem Workshoperleben dazu. Im besten Fall dauern diese emotionalen Täler nur kurz an, der Workshopmoderator hat diese „groan zones“ fest im Griff und führt die Workshopgruppe dort gut durch. Wenn – wie in unserem Fall – eine sehr heterogene Gruppe (gut für das Gesamtergebnis!) zusammenarbeitet, ist machmal auch die „groan zone“ schlicht heterogener und intensiver spürbar. Grübelei zu Ende.

Fast: „when a discussion loses focus or becomes confusing, it can appear to many people that the process is heading out of control. Yet this is not necessarily what’s really going on. Sometimes what appears to be chaos is actually a prelude to creativity.“ (Kaner et al., 2007, S. 5). Danke, Sam!

 

Veröffentlicht unter OC Inside, Strategy & Methods | Verschlagwortet mit , , , , , , , , , | Kommentar hinterlassen