Using Azure Containers with Paas services; a containerized cloud app example.

Welcome to the new Era of developing software; now you can fully focus on your solution and you don’t have to worry about topics like:
– dependency management
– (high) availability/scaling issues
– monitoring
– security

code you can find here, youtube flic

Motivation/ Why

Because it’s fun! and I love to show you how easy it is to start with an idea and end up in something that is usable in a very short period of time.

In this example I am using the following technologies:

  • python; code around the shell scripts for timing results, persisting and getting stuff from redis cache
  • java; springboot code that can only be accessed by authenticated users, like shown here
  • docker; to containerize my code
  • managed kubernetes on azure (aks); this provides a container orchestration solution on Azure where I don’t have to worry about setting up and maintaining machines, as this is available as a PAAS service. I am using version 1.81 so I can use cronjobs out of the box.
  • azure container instance (aci); serverless solution on azure to host single docker image, used for hosting the (java) frontend app.
  • azure container registry (acr); serverless solution on azure for a private docker registry; contains all the builds
  • redis cache; an open source solution for storing and accessing (temp) data; this is made available as a Paas service on Azure
  • cosmos db; microsofts’ document database, like mongodb. This database can be globally scaled and is available as a Paas service on Azure.
  • azure key vault; An enterprise ready cloud solution, with all the required security certifications. This stores my secrets (for eg passwords) and ceritificates.

NewImage

What does it do:

Provision; with the Azure CLI it retrieves all the DS2 machines per region and stores the machine/region in redis cache. Build: On scheduled base the vmcr8er will retrieve a value from the cache and based on these values it will create the machine in the region. It will measure the time that it has taken to build the machine and will persist the results in the cosmosdb. Show: The frontend app (once you are authenticated) will retrieve the values and calculate an average of the build per region. Averages longer than 3 minutest (180 sec) are considered slow builds. This is how it looks like:

This is how we do it:

  1. Get the latest sources for this project:  git clone https://github.com/chrisvugrinec/azure-vm-weathermap.git
  2. cd to scripts and then run the create_all script to create all the required (Azure) resources:  ./create-all.sh
  3. Prepare keyvault;   step 1 -2
    1. Create the vmcr8tester-redis-pw secret in keyvault and give it the value from the primary redis cache key
    2. Create the vmc8tester-cosmosdb-pw secret in keyvault and give it the value from the primary redis cache key
    3. Make sure that [ solution name ] gets the following authorization on the secrets of this vault: get/list and set or select the template “Secret Management”
  4. Prepare CosmosDB; create DB database, azurevms collection with partition key /id
  5. Kubernetes stuff
    1. On your local machine get the kubernetes credentials with the following command: az aks get-credentials -n [ NAME OF YOUR AKS CLUSTER ] -g [ NAME OF YOUR RESOURCEGROUP ], this will copy the ./kube/config file from the master to your local machine so you can talk to the API server
    2. Create the secret for accessing the private registry with the following command:  kubectl create secret docker-registry [ solution name ] –docker-server=[ solution name ].azurecr.io –docker-username=[ solution name ] –docker-password=[ primarey registry key ] –docker-email=[ your email ]:
  6. Create Provision job
    1. cd to backend/provision and do ./create.sh
    2. Docker login [ your solutionname.cvugrinecapp1.azurecr.io ] and then push the provision image to your private registry:  docker tag [ your image name:1.0 ] [ your registry URL/your image name:latest ], docker push [ your registry URL/your image name:latest ]
    3. Go to backend/kube and edit the provision-job.yaml (don’t forget to change your secret ), then create the job with the following command: kubectl create -f provision-job.yaml (use the example as template)
  7. Create VM create job
    1. cd to backend/vmcr8tester and do ./create.sh
    2. Docker login [ your solutionname.cvugrinecapp1.azurecr.io ] and then push the provision image to your private registry:  docker tag [ your image name:1.0 ] [ your registry URL/your image name:latest ], docker push [ your registry URL/your image name:latest ]
    3. Go to backend/kube and edit the create-job.yaml (don’t forget to change your secret ), then create the job with the following command: kubectl create -f create-job.yaml (use the example as template)
  8. Create Frontend with Container Instance
    1. change the properties in the frontend/java/src/main/resources/application.properties
    2. mvn clean build
    3. docker build -t [ your container url ]/someimage:latest .
    4. docker push [ your container url ]/someimage:latest
    5. ./createContainerInstance.sh
    6. change the reply URL in Azure AD to your container instance (you can see the container instance with the following command: az container list -o table)
    7. grant permissions to this user to access the azure ad tenant
  9. Setup OMS logging
    1. create workspace, by adding Log Analytics to your resource group
    2. get your workspace id and key, go to your workspace, then to settings, connected sources, linux machines
    3. edit the backend/oms/omsagent.yaml file (check the WSID and KEY section)
    4. create the deployment with kubectl create -f omsagent.yaml
    5. enable your oms agent logging, go to marketplace (solutions gallery), Select Application and Insights and then Container Monitor solutions, you will see something cool things like this:

Here is a screenshot of OMS logging which contains a query for the logging of the provision container:

Selenium – automated frontend testing

Intro

Iedereen die het nut en belang van unit testen en geautomatiseerd testen begrijpt zal zich op een gegeven moment afvragen hoe men de bepaalde handelingen van webapplicaties kan naspelen en testen op expectations…Er zijn verschillende tools op de markt  (zowel commercieel als open source) die bepaalde acties kunnen recorden en afspelen, bijv. Mercury LoadRunnen er Grinder.

Al enkele jaren bestaat ook selenium. In het kort:met Selenium kan je met verschillende programmeertalen (ook JAVA) tests schrijven op basis van recorded sessions.
De 2 voornaamste methodes die Selenium gebruikt om sessies na te spelen is: via een eigen proxy server of via een webClient/ Driver. (Selenium Server of via Selenium Client Driver )
Hiernaast bevat selenium een (test)API (Selenium Client Drivers)  en een IDE die als plugin in de browser (firefox) geinstalleerd kan worden. (Selenium IDE )

Uiteraard is dit heel beknopt, maar je kan van alles op het internet vinden, ik heb de bronnen in de onderstaande bronvermelding gebruikt:

In dit artikel laat ik zien hoe ik de volgende stappen van de portal heb geautomatiseerd en op verwachtingen heb getest:

  • Opvragen van website
  • Inloggen op site
  • Opnemen van 100 EUR
  • Rekening overzicht opvragen
  • Bekijken of opneembaar bedrag met 100EUR is afgenomen

Opzetten omgeving

Wat heb je nodig, (ik laat alleen zien hoe ik het aan de praat heb gekregen…dit behoeft dus niet de ultieme waarheid te zijn…)

Alle download vind je op deze pagina:    http://seleniumhq.org/download/

  • Werkende Eclipse omgeving met JUnit, maak alvast een standaard java projectje aan
  • Download en installeer de Selenium IDE (FIREFOX plugin)
  • Download de selenium server

Start de server met het volgende commando:

java -jar selenium-server-standalone-<version-number>.jar -firefoxProfileTemplate “path to the profile”

Maak eerst een firefox profiel aan:

firefox.exe -ProfileManager -no-remote

Reden hiervoor is dat het erop lijkt dat Selenium altijd een eigen nieuw profiel gebruikt en aanmaakt bij iedere nieuwe selenium sessie…dit wil je niet aangezien je bijvoorbeeld niet telkens certificaten wilt accepteren. Eenmaal je profiel aangemaakt zorg ervoor dat het SSL certificaat voor de portal is toegevoegd:   In firefox: EXTRA –> OPTIES –> Geavanceerd –> Encryptie –>Certificaten bekijken –> Tabblad servers….daar moet het volgende te zien zijn:

Dus het certificaat van  portala.ota.dom:443 moet “Voor altijd” geaccepteerd zijn…

Als dat allemaal gedaan is, dan moet je de server opstarten met het volgende commando:

java -jar selenium-server-standalone-2.25.0.jar -firefoxProfileTemplate “c:\Documents and Settings\chris\selenium”

Hier ben ik er dus vanuit gegaan dat het eerder gemaakte profiel in de volgende directory staat:  “c:\Documents and Settings\chris\selenium”

Telkens als selenium nu een sessie afvoert via de server…wordt dit profiel gebruikt en dus niet een nieuw profiel per sessie.

Maken/ Opnemen van (JAVA) Sessie

In je firefox browser (waar de Selenium IDE is geinstalleerd) start je de IDE: Extra –> Selenium IDE , je krijgt dan het volgende scherm te zien:

Druk op het rode knopje (RECORD) en ga met de browser naar de volgende URL:

https://portala.ota.dom/wps/portal/cp en op de site click je op het menu item “Mijn Interbank”, je selenium IDE ziet er dan ongeveer zo uit:

Ga zo door totdat je alle hebt opgenomen wat je wilt….

Nu komt de TRUC:
Eenmaal klaar met opnemen druk je weer op de RODE knop en dan op Bestand –> Export TestCase AS –> Java JUNIT Remote Control ( is dus met server)….je krijgt dan bijv de volgende Java code:

Maken van bruikbare tests

Copieer deze code in je java eclipse projectje…zorg ervoor dat in je Java library path alle JARS van de Selenium web client staan…dat ding wat je eerder gedownload hebt

Nu is het aan jou om bruikbare testcases en expectations te schrijven…hieronder heb je de sourcecode van iets wat ik gemaakt heb…..Als je de eerdere stappen hebt gevolgd kan je de code als JUNIT testcase runnen…

package com.cacf.poc.selenium;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
import com.thoughtworks.selenium.*;
import org.apache.commons.lang.NumberUtils;
import org.apache.commons.lang.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class InterbankTestCaseRC {
    public enum RekeningStatus {
        VOOR_OPNAME, NA_OPNAME 
    }
    DefaultSelenium selenium = null;
    
    @Before
    public void setUp() throws Exception {
        selenium = new DefaultSelenium(“127.0.0.1”, 4444, “*chrome”, “https://portala.ota.dom/wps/portal/cp/”);
        selenium.start();
    }    

    private Double getSaldo(InterbankTestCaseRC.RekeningStatus rekeningStatus) throws ParseException{
        String opneembaarSaldo = null;
        switch(rekeningStatus){
          case VOOR_OPNAME:
              opneembaarSaldo = selenium.getText(“//form[@id=’PC_7_ODD4BB1A0GKNF0IT9FUL1O2080_viewContractDetailsForm’]/fieldset/div[6]/span”);    
           break;
           case NA_OPNAME:
              opneembaarSaldo = selenium.getText(“//div[@id=’mainContent’]/table/tbody/tr/td[2]/table/tbody/tr/td/table/tbody/tr/td/div/div[2]/div/div/table/tbody/tr[2]/td/span”);    
           break;
        }
        String opneembaarSaldoZonderRuis = opneembaarSaldo.substring(opneembaarSaldo.indexOf(” “)+1, opneembaarSaldo.length());
        NumberFormat format = NumberFormat.getInstance(Locale.GERMAN);
        return format.parse(opneembaarSaldoZonderRuis).doubleValue();
    }
    
    @Test
    public void testInterbankOpnameRC() throws Exception {
        String opnameBedrag     = “100”;
        Double opnameBedragD     = NumberFormat.getInstance().parse(opnameBedrag).doubleValue();
        String wachtTijd          =  “30000”;
        String userName         = “ibcustto40”;
        String wachtWoord        = “password1”;
        
        //    Naar Interbank site en inloggen
        selenium.open(“/wps/portal/cp”);
        selenium.click(“link=Mijn InterBank”);
        selenium.waitForPageToLoad(wachtTijd);
        selenium.click(“css=img[alt=\”Inloggen\”]”);
        selenium.waitForPageToLoad(wachtTijd);
        selenium.type(“name=username”, userName);
        selenium.type(“name=password”, wachtWoord);
        selenium.click(“css=button[type=\”submit\”]”);
        selenium.click(“css=button[type=\”submit\”]”);
        selenium.waitForPageToLoad(wachtTijd);
        
        //    Opnemen van bedrag
        selenium.click(“link=Opnemen Saldo”);
        selenium.waitForPageToLoad(wachtTijd);
        Double saldoVoorOpname = getSaldo(RekeningStatus.VOOR_OPNAME);
        System.err.println(“Voor de opname: “+saldoVoorOpname);
        selenium.click(“name=targetPage”);
        selenium.waitForPageToLoad(wachtTijd);
        selenium.type(“id=PC_7_ODD4BB1A0GKNF0IT9FUL1O2080_amountEuros”, opnameBedrag);
        selenium.click(“id=PC_7_ODD4BB1A0GKNF0IT9FUL1O2080_next”);
        selenium.waitForPageToLoad(wachtTijd);
        selenium.click(“id=PC_7_ODD4BB1A0GKNF0IT9FUL1O2080_confirmedCheckbox”);
        selenium.click(“id=PC_7_ODD4BB1A0GKNF0IT9FUL1O2080_next”);
        selenium.waitForPageToLoad(wachtTijd);

        //Rekening overzicht bekijken, evalueer opneembedrag na de opname    
        selenium.click(“link=Opvragen Rekeningoverzicht”);
        selenium.waitForPageToLoad(wachtTijd);

        Double saldoNaOpname = getSaldo(RekeningStatus.NA_OPNAME);
        System.err.println(“Na de opname: “+saldoNaOpname);

        
        //    Check Saldo voor opname groter dan saldo na opname
        assertTrue(“Saldo NA Opname (“+saldoNaOpname+”) is niet kleiner dan saldo VOOR opname (“+saldoVoorOpname+”)!!!”,saldoNaOpname<saldoVoorOpname);
        
        //    Uiteraard moet het opneembaar saldo na de opname met het bedrag afgenomen zijn dat is opgenomen         
        assertTrue(“Saldo VOOR Opname (“+saldoVoorOpname+”) min saldo NA opname (“+saldoNaOpname+”) is niet gelijk aan opnamebedag a: “+opnameBedrag+”!!!”,saldoVoorOpname-saldoNaOpname==opnameBedragD);
        
    }

    @After
    public void tearDown() throws Exception {
        selenium.stop();
    }

}

Handige TIP:

Het is niet makkelijk om de elementen te vinden via XPath expressie…als je de selenium IDE in je firefox hebt geinstalleerd kan je bijv het volgende doen:

Ga naar een pagina, selecteer een element en click met je rechtermuisknop…

Als je dit gerecorded hebt…heb je meteen de code en XPATH expressie te pakken…

Bronnen

  • http://code.google.com/p/selenium/wiki/GettingStarted
  • http://www.slideshare.net/Vooch1/selenium-rc-presentation-20110104

Create Weblogic JMS Web Application

While you landed on this page you probably googled on one of these Terms:

JMS, Queue, Browser, Spring, Web App, Java, JMSDestinationRuntimeMBean, JMSMessageInfo, TextMessage or CompositeData
You found dozens of websites which will tell you how to create Weblogic JMS related tools using Python.. ( I liked is this one: http://weblogicserver.blogspot.com/2010/07/using-wlst-script-to-list-messages-from.html ) but finding out HOW to do it in java is less easy to find….even if you browse the Java API’s…you will find no examples.

I did some research and found out how to get JMS Queue info/ functions using java code…here it is, hope you can use it…

Below you find a method which returns an (Array)List of a message Type names JmsMessage.

  • JmsMessage is in my case just a java bean which contains the name and the JMS message body.
  • as Input the most important parameter is the (Array) List QueueInfo parameter. The most important property in the QueueInfo object is the JMSDestinationRuntimeMBean, this can only be set if you have a connection to the Managed Server and looked up the queue….

[java]
public List<JmsMessage> getQueueMessages(String queueName ,List<QueueInfo> allQueues, String msgId) throws ManagementException, OpenDataException, JMSException{

List<JmsMessage> result = new ArrayList<JmsMessage>();

// This local private method gets the QueueInfo Object from the List of Queues
QueueInfo queue = getQueueFromList(queueName, allQueues);

JMSDestinationRuntimeMBean jmsDestRtMBean = queue.getJmsDestRuntimeMBean();

// The cursor is a string that represents current position within the array of messages
String cursor = jmsDestRtMBean.getMessages(msgId, 0);
// Determine the size of the array of messages, needed for getting the complete array
long cursorSize = jmsDestRtMBean.getCursorSize(cursor);
// The Actual array of JMS Messages
CompositeData[] jmsMessages = jmsDestRtMBean.getNext(cursor, (int) cursorSize);
// Iterate over the JMS Message array

for(CompositeData jmsMessage : jmsMessages){
String msg = null;

// This object wrapper is needed in order to get the getHandle result…..
//  this will jump to the actual message within the array

JMSMessageInfo jmsInfo = new JMSMessageInfo(jmsMessage);
long handle = jmsInfo.getHandle();

// This is the funny part…..in stead of getting message from the array
// you do a getMessage from the JMSDestinationRuntimeMBean using the determined cursor and handle
CompositeData compData = jmsDestRtMBean.getMessage(cursor,handle);

// Wrap this object again with the JMSMessageInfo object, than you can get the message…
// this works only with (XML)text messages of course….
jmsInfo = new JMSMessageInfo(compData);
WLMessage wlm = jmsInfo.getMessage();
if(wlm instanceof TextMessage){

//  Setting the JMS body to our result list
TextMessage tmX = (TextMessage)wlm;
msg = tmX.getText();
}else{
log.debug(wlm.toString());
}
JmsMessage jmsMesg = new JmsMessage();
jmsMesg.setBody(msg);
// In my example I have set the propery MESSAGE_ID to the JMS Message, this is the way to get the property
jmsMesg.setMsgIdPropery(jmsInfo.getMessage().getStringProperty("MESSAGE_ID")); result.add(jmsMesg);
}
return result;
}

/*
Collects the needed queueinformation per domain
*/
public List<QueueInfo> collectQueueInfo(DomainHolder domainParam, String env){
List<QueueInfo> result = new ArrayList<QueueInfo>();
try {
DomainRuntimeServiceMBean domainRuntimeServiceMBean =
(DomainRuntimeServiceMBean)
MBeanServerInvocationHandler.<wbr>newProxyInstance(domainParam.<wbr>getConnection(),
new ObjectName(<wbr>DomainRuntimeServiceMBean.<wbr>OBJECT_NAME));
ServerRuntimeMBean[] serverRTMBeans =
domainRuntimeServiceMBean.<wbr>getServerRuntimes();
for(ServerRuntimeMBean serverRTMBean : serverRTMBeans){
JMSRuntimeMBean jmsRTMb = serverRTMBean.getJMSRuntime();
JMSServerRuntimeMBean[] jmsSrvrRTMbs = jmsRTMb.getJMSServers();
for(JMSServerRuntimeMBean jmsSrvrRTMb : jmsSrvrRTMbs){
JMSDestinationRuntimeMBean[] jmsDestRTMBeans =
jmsSrvrRTMb.getDestinations();
for(JMSDestinationRuntimeMBean jmsDestRTMBean : jmsDestRTMBeans ){
jmsDestRTMBean.<wbr>getMessagesCurrentCount();
QueueInfo queue = new QueueInfo();
queue.setDomainName(<wbr>domainParam.getName());
queue.setName(jmsDestRTMBean.<wbr>getName());
queue.setState(jmsDestRTMBean.<wbr>getState());
queue.setMessageHigh(<wbr>jmsDestRTMBean.<wbr>getMessagesHighCount());
queue.setCurrentMessages(<wbr>jmsDestRTMBean.<wbr>getMessagesCurrentCount());
queue.setCurrentConsumers(<wbr>jmsDestRTMBean.<wbr>getConsumersCurrentCount());
queue.setJmsDestRuntimeMBean(<wbr>jmsDestRTMBean);
queue.setEnv(env);
result.add(queue);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}

public Map<String,String> collectQueueConfigInfo(<wbr>DomainHolder domainParam){
Map<String, String> result = new HashMap<String, String>();
try {
DomainRuntimeServiceMBean domainRuntimeServiceMBean =
(DomainRuntimeServiceMBean)
MBeanServerInvocationHandler.<wbr>newProxyInstance(domainParam.<wbr>getConnection(),
new ObjectName(<wbr>DomainRuntimeServiceMBean.<wbr>OBJECT_NAME));
DomainMBean dem = domainRuntimeServiceMBean.<wbr>getDomainConfiguration();
JMSSystemResourceMBean[] jmsSRs = dem.getJMSSystemResources();

for (JMSSystemResourceMBean jmsSR : jmsSRs){
QueueBean[] qbs = jmsSR.getJMSResource().<wbr>getQueues();
for (QueueBean qb : qbs){
result.put("QUEUE_"+qb.<wbr>getName(),qb.getJNDIName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}

[/java]

Automated testing of OSB Services

Changed my opinion about automated testing of OSB services.(see last article)
In stead of focussing on linking the input to the output, I am making the assumption that I am the only one testing on the DEV environment. Fair and reasonable assumption and fairly easy to implement…..

The assumption:
The development environment is using the Continuous Integration strategy. After each build and deployment automated testing will be done on the DEV environment.

My automated Junit/ XMLUnit example is executing the following steps:

  • Posts a valid input XML file to a TestFacade
  • The Facade writes the input (from the body) to a directory
  • Test does a Thread.sleep (giving the OSB Interface the time to do it’s thing)
  • OSB
  •      Proxy Service reads (with JCA File Adapter) an XML file
  •      To Queue via Business Service
  •      Proxy Service is doing VETRO stuff to the message
  •      Business Service is writing to FTP server
  • Test/ Thread awakens and picks up the file
  • Actual output file is validated against XML schema using xmlunit
  • Actual output file is validated using xmlunit

The following technologies are being used: maven/ xmunit (for schema and xpath validations/ junit/ java/ apache-commons (for the FTP client)/ apache-httpclient (for the http post)

Maven pom.xml file

[sourcecode]

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<!– BASIC –>
<groupId>com.datalinks</groupId>
<artifactId>testxmlvalidtion</artifactId>
<version>0.0.1-SNAPSHOT</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<scope>compile</scope>
</dependency>
</dependencies>
<!– /BASIC –>

<!– BUILD –>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<!– /BUILD –>

</project>

[/sourcecode]

Later you can add a task to bamboo that will automatically checkout the test project and execute the following maven tasks…clean and test
But of course you can also manually execute the test in a shell environment…

  • mvn clean
  • mvn -o test

The -o ensures that you use the local repository (make sure that you have the dependencies in your local respository then) In order to run this you need to have at least the following installed: JRE (also set the JAVA_HOME setting), installation of maven 2x or higher (also make sure you have the MVN_HOME or M2_HOME environment variable set to the path of your maven installation)….in your maven installation directory you will have a settings.xml file. I use this file to set the directory for the local maven repository, I do this with the following property

[sourcecode]localRepository>/path/to/local/repo</localRepository>[/sourcecode]

Your Java project should contain the following directory structure

[code]
PROJECTDIR
—pom.xml (file)
—src
——main
———java
————[package directories]
——test
———java
————[package directories]
[/code]

When you do a mvn test or package (not using the -Dmaven.test.skip=true option) maven will know that it needs to execute the tests that are in the src/test/java directory (and it sub directories of course)
Assuming you use eclipse (OEPE) as your IDE, and you have the M2_REPO variable set to the path of your local repository…you can create the project structure (and set the proper classpath for your project) by typing

  • mvn eclipse:eclipse

TestFacade
Create a proxyService that has Service Type: Messaging Service and input TEXT, this service can do a callout which persist the body to a preconfigured directory (my implementation uses a parameter in the header, and based on the parameter SERVICE_NAME, it persists files in different directories…using the OSB Routing table). In stead of using JCA I prefer to do a simple JAVA call for writing the file:

[source]

package com.datalinks.testexample;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.xmlsoap.schemas.soap.envelope.impl.BodyImpl;

public class CustomFileWriter {
public static void writeFile(String fileName, String directory, BodyImpl content) throws IOException{
String tmpString = content.stringValue(); tmpString = tmpString.replaceFirst("<xml-fragment>", "");
tmpString = tmpString.replaceFirst("</xml-fragment>", "");
FileWriter fstream = new FileWriter(directory+fileName);
BufferedWriter out = new BufferedWriter(fstream);
out.write(tmpString);
out.close();
}
}
[/source]

the java callout has 3 parameters: filename, directory and the OSB $body variable…which in java code is equal to the org.xmlsoap.schemas.soap.envelope.impl.BodyImpl object.
Also notice that I am removing the <xml-fragment> tags….this is added by OSB and changes the content of the XML file…so it needs to go.

Java code that is able to post HTTP call (with body)

[java]

package com.datalinks.testexample;

import java.io.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

public class HttpClientTester {
static Logger logger = Logger.getLogger(HttpClientTester.class);
private static String testFacadeUrl="http://localhost:7001/TestServices/ProxyServices/TestServicesFacade_PS?SERVICE_NAME=";

public static String callService(String serviceName) throws Exception {
String result = null;
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(testFacadeUrl+serviceName);
HttpResponse response = null;
response = httpclient.execute(httppost);
if(response.getStatusLine().getStatusCode()!=200){
throw new Exception("Exception calling "+serviceName+" statusCode "+response.getStatusLine().getStatusCode());
}
HttpEntity entity = response.getEntity();
if (entity != null) {
long len = entity.getContentLength();
if (len != -1 && len < 2048) {
result = EntityUtils.toString(entity);
}
}
return stripClobMessageFromHeaderAndFooter(result);
}
public static String callService(String serviceName, String body) throws Exception {

String result = null;
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(testFacadeUrl+serviceName);
StringEntity entityIn = new StringEntity(body);
httppost.setEntity(entityIn);
HttpResponse response = null;
response = httpclient.execute(httppost);
if(response.getStatusLine().getStatusCode()!=200){
throw new Exception("Exception calling "+serviceName+" statusCode "+response.getStatusLine().getStatusCode());
}
HttpEntity entity = response.getEntity()
if (entity != null) {
long len = entity.getContentLength();
if (len != -1 && len < 2048) {
result = EntityUtils.toString(entity);
}
return stripMessageFromHeaderAndFooter(result);
}
}
}
[/java]

Grinder notes; play recorded http session for loadtest

set classpath set classpath=c:\CHRIS\WORK\Dowloads\grinder-3.4\lib\grinder.jar

Record http session

Start the proxy…all HTTP requests from your browser should go past this proxy

java net.grinder.TCPProxy -console -http > nameOfAPythinFile.py

Make sure that your browser does all the requests via the proxy you just started: In your browser settings, set the proxy to localhost 8001 (for all protocols), 8001 is the default port for the proxy

After setting this proxy, do your http things in your browser, login to a page, search whatever you like to record. When finished; press stop on the dialogue that popped up earlier.

Do the Grinder recorded http session

Adjust your grinder.properties so that the Grinder process will use the Python script you just recorded. Then start the grinder process

java net.grinder.Grinder grinder.properties Start the console ..and record your measurements java net.grinder.Console

The console will connect to the grinder process, a lot of graphs will appear then.

How to start/stop Weblogic ALSB services with java code

With the following code you can connect to a Weblogic server get it’s context and manipulate it’s domain objects (starting/ stopping servers, change properties of the domain logging/ jdbc datasource properties etc etc)

In order to get the following code working you need to incorporate the following jar’s in your classpath:

  • weblogic.jar (from /bea alsb dir/modules)JMXServiceURL serviceURL = new JMXServiceURL(“t3”, hostname, port, “/jndi/” + DomainRuntimeServiceMBean.MBEANSERVER_JNDI_NAME); Hashtable h = new Hashtable(); h.put(Context.SECURITY_PRINCIPAL, username); h.put(Context.SECURITY_CREDENTIALS, password); h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, “weblogic.management.remote”); JMXConnectorFactory connection = JMXConnectorFactory.connect(serviceURL, h); MBeanServerConnection mbconn = connection .getMBeanServerConnection(); domainRuntimeServiceMBean = (DomainRuntimeServiceMBean) MBeanServerInvocationHandler.newProxyInstance(mbconn, new ObjectName(DomainRuntimeServiceMBean.OBJECT_NAME)); domainMBean = domainRuntimeServiceMBean.getDomainConfiguration();

 

// Now the ALSB specific related stuff:

// With the following code you can connect to an ALSB server (which is a weblogic server with ALSB templates/ deployments) get it’s context and manipulate it’s domain objects (starting/ stopping services, change properties etc etc)

// In order to get the following code working you need to incorporate the following jar’s in your classpath:

  • configfwk_1.1.0.0.jar (from /bea alsb dir/modules)
  • sb-kernel-api.jar (from /bea alsb dir/alsb/lib) SessionManagementMBean sm = (SessionManagementMBean) domainService.findService(SessionManagementMBean.NAME, SessionManagementMBean.TYPE, null); ALSBConfigurationMBean acmb =(ALSBConfigurationMBean)domainService.findService(ALSBConfigurationMBean.NAME + “.” + sessionName, ALSBConfigurationMBean.TYPE, null); // Create a session, it is wise to give the session a unique name sm.createSession(sessionName); // For Proxy services ProxyServiceQuery psQuery = new ProxyServiceQuery(); // For Business services BusinessServiceQuery bsQuery = new BusinessServiceQuery(); Set refs = acmb.getRefs(psQuery);

 

// configurationMBean for Proxy Services ProxyServiceConfigurationMBean proxyServiceConfigurationMBean = (ProxyServiceConfigurationMBean)domainService.findService(ProxyServiceConfigurationMBean.NAME + “.” + sessionName,ProxyServiceConfigurationMBean.TYPE, null); // configurationMBean for Business Services BusinessServiceConfigurationMBean businessServiceConfigurationMBean = (BusinessServiceConfigurationMBean)domainService.findService(BusinessServiceConfigurationMBean.NAME + “.” + sessionName,BusinessServiceConfigurationMBean.TYPE, null); // Iterate through a list of Busness Service and do stuff… refs = acmb.getRefs(bsQuery); for (Ref ref : refs) { // use the ref object to do things }

// When finished store your session to commit your changes String CLOSE_AND_COMMIT_REMARK = “some remark to identify your change with”; sm.activateSession(sessionName, CLOSE_AND_COMMIT_REMARK + sessionName);

Java yesterday’s date

Ever had to calculate yesterday’s date in a little java proggie… use the roll function of the Gregorian Caledar…

// Create the calendar object, default is todays date GregorianCalendar gc = new GregorianCalendar(); then go back… a day gc.roll(Calendar.DAY_OF_YEAR, -1);

Be aware …if it’s the 1st of January (new year…) then you need to roll back a year as well….