tisdag 28 oktober 2014

Spring boot - no more boilerplate


So, just loving the spring boot project. Spring has always been a nice framework but the constant xml hammering for the contexts have been clashing with my hatred of excessive configuration. Along came the spring annotations that made things much more user friendly but still is kind of boilerplate intensive when you just want to go go go. Enter the spring boot project.

Just add the spring boot parent to your artifact.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>[1.1.8.RELEASE,)</version>
</parent>

Boom. You now have all the boilerplate preconfigured by default in your project. Add a spring boot dependency and add a main method to start up the context and Bob (or Bub if you prefer) is your uncle. All you need is the enabling annotation and a main runnable class.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

and your class 

@EnableAutoConfiguration
@ComponentScan
public class Application {

    public static void main(String[] args) throws Exception {

        SpringApplication.run(Application.class, args);

    }

}

I double-dare you to not like this. Just try the spring security dependency. Works by scanning your classpath for key dependency classes and including predefined boilerplate. Just add the deps and boot will kick the config. When you get around to write your own configuration just exclude the boilerplate in the enable auto conf annotation. Like a glove. Or a unicorn. Or a funny cat.

fredag 28 juni 2013

XSLT för visualisering av XSD för t.ex. en webservice.

Nästa gång jag vill rendera XSD:er som HTML så kan jag utgå ifrån denna lilla snutt XSL. Det kan länkas till min xsd via en enkel

<?xml-stylesheet type="text/xsl" href="xsd_viewer.xsl"?>

Typ så här ser den ut, renderar alla complex- och simple types som egna tabeller med länkar till varandra samt en frän propertyslista längst upp:

<?xml version="1.0" encoding="utf-8"?>
<!--
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/1999/xhtml"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                version="2.0"
                exclude-result-prefixes="xs">
    <xsl:output method="xml" version="1.0" encoding="utf-8" indent="no"
                omit-xml-declaration="no"
                media-type="text/html"
                doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
                doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"/>

    <xsl:strip-space elements="*"/>

    <!-- Variables -->
    <xsl:variable name="css">

        html {
            background-color: white;
        }

        body {
            margin: 0;
            padding: 0;
            height: auto;
            font: normal 80%/120% Arial, Helvetica, sans-serif;
        }

        .header {
            margin: 5px;
            font-weight: bold;
        }

        table {
            margin: 5px;
        }

        table, td, tr {
            border-color: black;
            border-width: 1px;
            border-spacing: 0;
            border-collapse: collapse;
            border-style: solid;
            padding: 5px;
        }

    </xsl:variable>

    <!-- Renderpipe -->

    <xsl:template name="htmlRender" match="/">
        <html>
            <head>
                <title><xsl:value-of select="xs:schema/@targetNamespace"/></title>
                <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
                <style type="text/css"><xsl:value-of select="$css" disable-output-escaping="yes"/></style>
            </head>
            <body>
                <xsl:call-template name="renterSchemaTypeMatrix" />
                <xsl:call-template name="renderSchemaComplexTypes" />
                <xsl:call-template name="renderSchemaSimpleTypes" />
            </body>
        </html>
    </xsl:template>

    <xsl:template name="renterSchemaTypeMatrix" match="*">
        <table>
            <tr>
                <td class="header">Property</td>
            </tr>
            <xsl:call-template name="renderSchemaMatrix" />
        </table>
        <br/>
    </xsl:template>

    <xsl:template name="renderSchemaMatrix" match="*">
        <xsl:for-each select="child::*">
            <xsl:call-template name="renderMatrixRow"/>
            <xsl:for-each select="document(xs:include/@schemaLocation)">
                <xsl:call-template name="renderSchemaMatrix"/>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="renderSchemaComplexTypes" match="*">
        <xsl:for-each select="child::*">
            <xsl:call-template name="renderComplexTypes"/>
            <xsl:for-each select="document(xs:include/@schemaLocation)">
                <xsl:call-template name="renderSchemaComplexTypes"/>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="renderSchemaSimpleTypes" match="*">
        <xsl:for-each select="child::*">
            <xsl:call-template name="renderSimpleTypes"/>
            <xsl:for-each select="document(xs:include/@schemaLocation)">
                <xsl:call-template name="renderSchemaSimpleTypes"/>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="renderMatrixRow" match="*">
        <xsl:for-each select="xs:complexType">
            <xsl:for-each select="*">
                <xsl:for-each select="child::*">
                    <xsl:if test="@name != ''">
                        <xsl:if test="contains(@type, 'xs')">
                            <tr>
                                <td>
                                    <a href="#{parent::*/parent::*/@name}"><xsl:value-of select="parent::*/parent::*/@name"/></a>.<xsl:value-of select="@name"/>
                                </td>
                            </tr>
                        </xsl:if>
                    </xsl:if>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="renderComplexTypes" match="*">
        <xsl:for-each select="xs:complexType">
            <table>
                <tr>
                    <td class="header" colspan="4">
                        <a name="{@name}"><xsl:value-of select="@name"/></a>
                    </td>
                </tr>
                <tr>
                    <td class="header">Fältnamn</td>
                    <td class="header">Datatyp</td>
                    <td class="header">Beskrivning</td>
                    <td class="header">Multip.</td>
                </tr>
                <xsl:for-each select="*/xs:choice">
                    <xsl:for-each select="xs:element">
                        <tr>
                            <td><xsl:value-of select="@name"/></td>
                            <td>
                                <xsl:choose>
                                    <xsl:when test="not(contains(@type, 'xs'))">
                                        <a href="#{substring-after(@type,':')}">
                                            <xsl:value-of select="substring-after(@type,':')"/>
                                        </a>
                                    </xsl:when>
                                    <xsl:otherwise>
                                        <xsl:value-of select="substring-after(@type,':')"/>
                                    </xsl:otherwise>
                                </xsl:choose>
                            </td>
                            <td>
                                <xsl:value-of select="xs:annotation/xs:documentation"/>
                            </td>
                            <td>Del av val</td>
                        </tr>
                    </xsl:for-each>
                </xsl:for-each>
                <xsl:for-each select="*/xs:element">
                    <tr>
                        <td><xsl:value-of select="@name"/></td>
                        <td>
                            <xsl:choose>
                                <xsl:when test="not(contains(@type, 'xs'))">
                                    <a href="#{substring-after(@type,':')}">
                                        <xsl:value-of select="substring-after(@type,':')"/>
                                    </a>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:value-of select="substring-after(@type,':')"/>
                                </xsl:otherwise>
                            </xsl:choose>
                        </td>
                        <td><xsl:value-of select="xs:annotation/xs:documentation"/></td>
                        <td>
                            <xsl:choose>
                                <xsl:when test="@minOccurs!=''">
                                    <xsl:choose>
                                        <xsl:when test="@maxOccurs!=''">
                                            <xsl:value-of select="@minOccurs"/>..<xsl:value-of select="@maxOccurs"/>

                                        </xsl:when>
                                        <xsl:otherwise>
                                            <xsl:value-of select="@minOccurs"/>..1
                                        </xsl:otherwise>
                                    </xsl:choose>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:choose>
                                        <xsl:when test="@maxOccurs!=''">
                                            1..<xsl:value-of select="@maxOccurs"/>
                                        </xsl:when>
                                        <xsl:otherwise>1..1</xsl:otherwise>
                                    </xsl:choose>
                                </xsl:otherwise>
                            </xsl:choose>
                        </td>
                    </tr>
                </xsl:for-each>
            </table><br/>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="renderSimpleTypes" match="*">
        <xsl:for-each select="xs:simpleType">
            <table>
                <tr>
                    <td class="header" colspan="3">
                        <a name="{@name}"><xsl:value-of select="@name"/></a>
                    </td>
                </tr>
                <tr>
                    <td class="header">Namn</td>
                    <td class="header">Typ</td>
                    <td class="header">Begränsning</td>
                </tr>
                <tr>
                    <td><xsl:value-of select="@name"/></td>
                    <xsl:choose>
                        <xsl:when test="not(contains(xs:restriction/@base, 'xs'))">
                            <td>
                                <a name="{substring-after(@base,':')}">
                                   <xsl:value-of select="substring-after(xs:restriction/@base,':')"/>
                                </a>
                            </td>
                        </xsl:when>
                        <xsl:otherwise>
                            <td><xsl:value-of select="substring-after(xs:restriction/@base,':')"/></td>
                        </xsl:otherwise>
                    </xsl:choose>
                    <td>
                        <xsl:for-each select="xs:restriction/*">
                            <xsl:value-of select="substring-after(name(),':')"/> = <xsl:value-of select="@*"/><br/>
                        </xsl:for-each>
                    </td>
                </tr>
            </table><br/>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

fredag 10 augusti 2012

Dela groovyscript mellan testsviter i soapUI free

Eftersom det är festligt att kunna dela på script mellan sina testfall utan att behöva köpa soapUI Pro så tänkte jag komma ihåg hur man gör det. Ett par enkla steg är allt som behövs för att slippa härja.

Börja med att skapa en testsvit som man t.ex. kan kalla för 'script library'. Därefter skapar man med fördel ett testfall för varje paket man känner att man vill gruppera sina groovyscript i, för enkelhetens skulle kallar vi vårt demopaket för 'demo' som vi adderar ett ett teststeg till i form av ett groovyscript, här kallat 'DemoUtil' som jag enkelt väljer att fylla med följande stuff:

//Addera klassens instans till propsen
context.setProperty("demoUtil", new DemoUtil())
import com.eviware.soapui.SoapUI
public class DemoUtil {
  def static hello(log, testRunner) {
    log.info "Hello from DemoUtil"
  }
}

Sen kan man med ett enkelt handgrepp plocka upp den från propsen i sina andra testfall och exekvera hello om man vill med ett fint groovyscript som gör följande:

//Initiera lite o kör metoden
scripts = testRunner.testCase.testSuite.project.testSuites["script library"]
scripts.testCases["demo"].testSteps["DemoUtil"].run(testRunner, context)
context.demoUtil.hello(log, testRunner)

Och så krossas kakan. Bob blir din farbror och så vidare. Bra att ha kommaihåg prylar.

onsdag 2 november 2011

Java på OSX Lion

Om man vill köra Java 1.4 eller 1.5 i OSX Lion är det inte mycket att göra åt om man inte råkar komma över en variant av Leopard-tar.gz filerna för dessa. Sen kan man ju passa på att stoppa in dessa i OSX Frameworkkatalog och länka till dessa istället för att låta länkarna peka på 1.6.  

tar xzvf java.1.4.2-leopard.tar.gz
sudo mv 1.4.2 /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2-leopard
sudo rm /System/Library/Frameworks/JavaVM.framework/Versions/1.4
sudo rm /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2
sudo ln -s /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2-leopard/ /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2
sudo ln -s /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2 /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2

tar xzvf java.1.5.0-leopard.tar.gz 
sudo mv 1.5.0 /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0-leopard
sudo rm /System/Library/Frameworks/JavaVM.framework/Versions/1.5
sudo rm /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0
sudo ln -s /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0-leopard /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0
sudo ln -s /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0 /System/Library/Frameworks/JavaVM.framework/Versions/1.5

... och bob är din onkel.

torsdag 6 oktober 2011

Oracle XA

Eftersom det visade sig vara så att man måste granta rättigheter för att köra XA transaktioner på en Oracledatabas från en jboss så passar jag på att påminna mig själv om att det krävs för din dbuser som jag ska köra med från appservern.
Om man inte gör det dyker detta mysiga felmeddelande upp som en varning i loggen med cirka 3 minuters mellanrum.
2011-10-06 23:31:45,099 WARN  [com.arjuna.ats.jta.logging.loggerI18N] (Thread-12) [com.arjuna.ats.internal.jta.recovery.xarecovery1] Local XARecoveryModule.xaRecovery  got XA exception javax.transaction.xa.XAException, XAException.XAER_RMERR

Så passa på du med, granta dig själv till en bättre värld.
GRANT SELECT ON sys.dba_pending_transactions TO <dbuser>;
GRANT SELECT ON sys.pending_trans$ TO <dbuser>;
GRANT SELECT ON sys.dba_2pc_pending TO <dbuser>;
GRANT EXECUTE ON sys.dbms_system TO <dbuser>;

onsdag 23 mars 2011

Hotswappa sessioncontext i en ejb2-böna med spring.

Eftersom jag för andra gången glömde bort hur man sätter upp en fin liten hotswappable target source för att swappa in sessionskontextet i en gammal böna tänkte jag att jag lägger upp en liten komihåg på det nu.

Först tar vi och lägger till ett target i sessionsbönan vi ska swappa den från:

public class Bean extends AbstractStatelessSessionBean implements SessionBean {
private HotSwappableTargetSource sessionContextTarget;
protected void onEjbCreate() throws CreateException {
BeanFactory beanFactory = getBeanFactory();
sessionContextTarget = = (HotSwappableTargetSource) beanFactory.getBean("hotswappableSessionContext");
}
}

samt att vi lägger till själva swappen i set-metoden:
@Override
public void setSessionContext(SessionContext sessionContext) {
super.setSessionContext(sessionContext);
this.sessionContextTarget.swap(sessionContext);
}

Därefer passar vi på att konfigurera den i springxmlen,

<bean id="sessionContextBean" class="nu.danielsundberg.FejkSessionContext"/>
<bean id="hotswappableSessionContext" class="org.springframework.aop.target.HotSwappableTargetSource">
<constructor-arg><ref local="sessionContextBean"/></constructor-arg>
</bean> 

lägger till den injectad i vår andra böna vi vill ha access till contextet i
<property name="sessionsContext">
<ref local="sessionContextBean"/>
</property>
och avslutar med att lägga till den i mottagande bönan.
private SessionContext sessionsContext;
public void setSessionsContext(SessionContext sessionsContext) {
this.sessionsContext = sessionsContext;
}

Och bob är min onkel.

måndag 1 november 2010

@Hide på metoder i Android

Efter att ha letat oavbrutet i ungefär 2 timmar efter vettiga (eller på något sätt befintliga) sätt att tjuvtitta på en befintlig ström mot Audioslinger (Androids underliggande tjusiga ramverk som skjuter data på ljudhårdvaran) som man inte skapat själv i Androids medialibbar så har jag kommit fram till följande.

  1. Androids medialibbar suger hästdelar.
  2. Allt bra "kommer sen" (i det här fallet Open AL och mer native-nära funktioner)

Så tills vidare trodde jag förstås att jag var, som undomarna säger idag, rökt. Men av en magisk slump (eller idogt googlande) landade jag på implementationen av de medföljande visualiseringarna av musik i Androidkällkoden, där en metod med namnet "snoop"användes flitigt på mediaspelarklassen som jag ansåg vara värd en extra titt. Efter att ha förundrats över det faktum att jag tydligen inte kunde anropa denna fina metod (eller ens bevisa dess existens i min utvecklingsmiljö) fick jag en snabb lektion i en annotering med det snillrika namnet @Hide. Denna annotering används på metoder som inte anses vara dokumenterbar/förvaltningsbar i Androids källkod (men förmodligen kommer att bli det iom att den finns kvar). Eftersom jag inte har lust att kompilera några stubbar/bygga om Androidprylar från source kom jag raskt att tänka på perfektionen i att reflektera. Så utan mera omsvävningar, här kommer hur du anropar en metod i Android (förslagsvis snoopmetoden på MediaPlayer i det här fallet) på ett mer eller mindre tjusigt sätt tills den slutar gömmas:
short [] mVizData = new short[1024];
try {
  Class<MediaPlayer> myEvilMediaPlayer = (Class<MediaPlayer>) Class.forName(MediaPlayer.class.getName());
  try {
    Class[] parameterTypes = new Class[] {short[].class, int.class};
    Method snoop = myEvilMediaPlayer.getMethod("snoop", parameterTypes);
    snoop.setAccessible(true);
    Object[] arguments = new Object[2];
    arguments[0] = mVizData;
    arguments[1] = 0;
    int x = (Integer) snoop.invoke(myEvilMediaPlayer, arguments);
    System.out.println(x);
  } catch (SecurityException e) {
    e.printStackTrace();
  } catch (NoSuchMethodException e) {
    e.printStackTrace();
  } catch (IllegalArgumentException e) {
    e.printStackTrace();
  } catch (IllegalAccessException e) {
    e.printStackTrace();
  } catch (InvocationTargetException e) {
    e.printStackTrace();
  }
} catch (ClassNotFoundException e) {
  e.printStackTrace();
}
In your face @Hide annoteringen, det där är vad man får om man försöker gömma metoder för folk.