Showing posts with label groovy. Show all posts
Showing posts with label groovy. Show all posts

Wednesday, October 10, 2018

Nexus Groovy scripting

Huge issue in Nexus is that you can't export/import your Users/Groups/Privileges and Repository configuration. All you can do is to take a "backup", which ends of in a folder as a completely unreadable/unversionable format.

So I was looking for

when you run a Groovy script in Nexus, you have available a predefined variable "repository", which is of type org.sonatype.nexus.script.plugin.internal.provisioning.RepositoryApiImpl

This in turn contains a reference to a blobStoreManager org.sonatype.nexus.blobstore.api.BlobStoreManager and to a repositoryManager org.sonatype.nexus.repository.manager.RepositoryManager , plus a series of convenience methods to create commonly used repository formats (you are not expected to create anything fancy, most properties are assigned by default) and groups.

Key element is a org.sonatype.nexus.repository.config.Configuration object, again very disappointing since the configuration is represented by a "attribute" map (String, Map(String, Object)) which is really a stupid idea, too generic interface.

RepositoryManager has a Iterable<Repository> browse(); which returns a collection of org.sonatype.nexus.repository.Repository

Sample script:

import org.sonatype.nexus.repository.Repository

repository.repositoryManager.browse().each { Repository repo ->
    log.info("Repository: $repo")
    log.info("Repository Configuration: $repo.configuration")
}


this dumps in nexus.log the following content:

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=proxy, format=nuget, name='nuget.org-proxy'}
Repository Configuration: Configuration{repositoryName='nuget.org-proxy', recipeName='nuget-proxy', attributes={proxy={strictContentTypeValidation=true, contentMaxAge=1440, remoteUrl=https://www.nuget.org/api/v2/, metadataMaxAge=1440}, negativeCache={}, storage={blobStoreName=default}, nugetProxy={}, httpclient={connection={blocked=false, autoBlock=true}}}}

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=hosted, format=maven2, name='maven-releases'}
Repository Configuration: Configuration{repositoryName='maven-releases', recipeName='maven2-hosted', attributes={maven={versionPolicy=RELEASE, layoutPolicy=STRICT}, storage={writePolicy=ALLOW_ONCE, strictContentTypeValidation=false, blobStoreName=default}}}

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=hosted, format=maven2, name='maven-snapshots'}
Repository Configuration: Configuration{repositoryName='maven-snapshots', recipeName='maven2-hosted', attributes={maven={versionPolicy=SNAPSHOT, layoutPolicy=STRICT}, storage={writePolicy=ALLOW, strictContentTypeValidation=false, blobStoreName=default}}}

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=proxy, format=maven2, name='maven-central'}
Repository Configuration: Configuration{repositoryName='maven-central', recipeName='maven2-proxy', attributes={proxy={contentMaxAge=-1, remoteUrl=https://repo1.maven.org/maven2/, metadataMaxAge=1440}, negativeCache={timeToLive=1440, enabled=true}, storage={strictContentTypeValidation=false, blobStoreName=default}, maven-indexer={}, httpclient={connection={blocked=false, autoBlock=true}}, maven={versionPolicy=RELEASE, layoutPolicy=PERMISSIVE}}}

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=group, format=nuget, name='nuget-group'}
Repository Configuration: Configuration{repositoryName='nuget-group', recipeName='nuget-group', attributes={storage={blobStoreName=default}, nugetProxy={}, httpclient={}, group={memberNames=[nuget-hosted, nuget.org-proxy]}}}

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=hosted, format=nuget, name='nuget-hosted'}
Repository Configuration: Configuration{repositoryName='nuget-hosted', recipeName='nuget-hosted', attributes={storage={writePolicy=ALLOW, blobStoreName=default}}}

Repository: RepositoryImpl$$EnhancerByGuice$$c5f0822b{type=group, format=maven2, name='maven-public'}
Repository Configuration: Configuration{repositoryName='maven-public', recipeName='maven2-group', attributes={maven={versionPolicy=MIXED}, group={memberNames=[maven-releases, maven-snapshots, maven-central]}, storage={blobStoreName=default}}}





which is pretty good result, at least you can capture in one go all the configuration of all your repositories.



This task will delete all your repos:

import org.sonatype.nexus.repository.Repository

repository.repositoryManager.browse().each { Repository repo ->
    log.info("DELETE Repository: $repo")
    repository.repositoryManager.delete("$repo.name")
}


All the predefined variables are

core which is a org.sonatype.nexus.internal.provisioning.CoreApiImpl

repository which is a org.sonatype.nexus.script.plugin.internal.provisioning.RepositoryApiImpl

blobStore which is a org.sonatype.nexus.internal.provisioning.BlobStoreApiImpl
createFileBlobStore(final String name, final String path)
org.sonatype.nexus.blobstore.api.BlobStoreManager blobStoreManager 

security which is a org.sonatype.nexus.security.internal.SecurityApiImpl
User addUser(final String id, final String firstName, final String lastName, final String email, final boolean active,
final String password, final List roleIds)
Role addRole(final String id, final String name, final String description, final List privileges,
final List roles)
User setUserRoles(final String userId, final List roleIds)

If you do security.getSecuritySystem() you get an instance of this:
https://github.com/sonatype/nexus-public/blob/master/components/nexus-security/src/main/java/org/sonatype/nexus/security/SecuritySystem.java


Good is that if you clone the github repo nexus-book-examples you can directly open the APIs in file:///home/centos/gitclones/nexus-book-examples/scripting/apidocs/index.html


List all users with their roles

import groovy.json.JsonOutput
users = security.getSecuritySystem().listUsers()
userjson = JsonOutput.toJson(users)
log.info("USERS $userjson")


or also

import org.sonatype.nexus.security.user.UserSearchCriteria

users = security.getSecuritySystem().searchUsers(new UserSearchCriteria())
log.info("users=" + users)


Add users and roles:

privileges = [
            "nx-search-read",
            "nx-repository-view-*-*-read",
            "nx-repository-view-*-*-browse",
            "nx-repository-view-*-*-add",
            "nx-repository-view-*-*-edit",
"nx-apikey-all"]

security.addRole("deployer", "deployer", "deployment on all repositories", privileges, [])

security.addUser(userName, firstName, lastName, email, true, password, ["deployer"])



creating blobstores:


def list = ["dockerGroup", "mynpm", "pippo", "ivy", "dockerhosted", "dockerProxy", "jcenter", "pythonProxy"]
for (item in list) {
    log.info("creating blobstore " + item)
    blobStore.createFileBlobStore(item, item)
}




creating hosted repositories

import org.sonatype.nexus.repository.storage.WritePolicy;
import org.sonatype.nexus.repository.maven.VersionPolicy;
import org.sonatype.nexus.repository.storage.WritePolicy
import org.sonatype.nexus.repository.maven.LayoutPolicy


repository.createDockerHosted(name = 'pippo', httpPort = 8123, httpsPort = null, blobStoreName = 'docker', strictContentTypeValidation=true, v1Enabled=true, writePolicy = WritePolicy.ALLOW, forceBasicAuth=false)

repository.createMavenHosted(name = 'ivyhosted', blobStoreName = 'ivy', strictContentTypeValidation = true, versionPolicy = VersionPolicy.RELEASE, writePolicy= WritePolicy.ALLOW_ONCE, layoutPolicy=LayoutPolicy.PERMISSIVE )




You cannot delete anonymous, the only way is to update it:

import org.sonatype.nexus.security.user.*
import org.sonatype.nexus.security.role.*

// the following 6 lines are not required
anonymous = security.getSecuritySystem().getUser("anonymous", "default")
log.info("Anonymous before=" + anonymous)
Set allRoles = security.getSecuritySystem().listRoles();
log.info("allRoles=" + allRoles)
advRole = allRoles.find{it.roleId=='ADVRole'}
log.info("advRole=" + advRole)

// these 2 lines below do the job
advRoleIdentifier = new RoleIdentifier('default', 'ADVRole');
security.getSecuritySystem().setUsersRoles("anonymous", "default", [advRoleIdentifier].toSet())



Script to create/update a role (without affecting existing users using that role, if existing)



import org.sonatype.nexus.security.user.*
import org.sonatype.nexus.security.role.*
import static org.sonatype.nexus.security.user.UserManager.DEFAULT_SOURCE

privileges = [
            "nx-search-read",
            "nx-repository-view-*-*-read",
            "nx-repository-view-*-*-browse",
            "nx-repository-view-*-*-add",
            "nx-repository-view-*-*-edit",
            "nx-apikey-all"
]

createOrUpdateRole("pippo", privileges, [])
createOrUpdateUser("pippouser", [ "pippo", "nx-admin" ])

def createOrUpdateRole(rolename, privileges, roles) {
    log.info("calling createOrUpdateRole with parameters rolename=" + rolename + " privileges=" + privileges + " roles=" + roles)
 Set allRoles = security.getSecuritySystem().listRoles()
 Role role = allRoles.find{it.roleId==rolename}
 if (role != null) {
     log.info("existing role=" + role)
  role.setPrivileges(privileges.toSet())
  role.setRoles(roles.toSet())
  log.info("updating role=" + role)
  // security.securitySystem.getAuthorizationManager(DEFAULT_SOURCE).deleteRole(role.roleId)
  security.securitySystem.getAuthorizationManager(DEFAULT_SOURCE).updateRole(role)
  log.info("role updated=" + role)
 }
 else {
  log.info("adding role " + rolename)
  security.addRole(rolename, rolename, rolename, privileges, roles)
  log.info("role " + rolename + " successfully added")
 }
}



def createOrUpdateUser(username, roles) {
 log.info("calling createOrUpdateUser with parameters username=" + username + " roles=" + roles)
 Set allUsers = security.getSecuritySystem().listUsers()
 User user = allUsers.find{it.userId == username}
 if (user != null) {
  log.info("updating existing user=" + user)
  Set roleIdentifiers = new HashSet()
  roles.each{ role -> roleIdentifiers.add(new RoleIdentifier("default", role))}
  security.getSecuritySystem().setUsersRoles(username, "default", roleIdentifiers)
 }
 else {
  security.addUser(username, username, username, username + "@gmail.com", true, username, roles)
 }
}






Sunday, September 30, 2018

Nexus and Groovy for Setup Automation

Amazingly few people automate their Nexus administration. I guess the fault lies mostly in the company behind Nexus, who does very little to make their API usable and well documented.

This post https://blog.soebes.de/blog/2017/10/02/nexus-scripted-setup/ made me discover this API:

https://github.com/sonatype/nexus-public/blob/master/plugins/nexus-script-plugin/src/main/java/org/sonatype/nexus/script/plugin/RepositoryApi.java

Very good reading also here https://support.sonatype.com/hc/en-us/articles/115015812727-Nexus-3-Groovy-Script-development-environment-setup about using the Nexus book examples to automate the execution of these Groovy/Java scripts.

References http://www.javamonamour.org/2018/03/nexus-repository-administration.html on same topic of Automation (via REST api)

Tuesday, February 20, 2018

groovysh and X11

Running groovysh I get this error:


java.awt.AWTError: Can't connect to X11 window server using 'myserver:0.0' as the value of the DISPLAY variable

Really weird.... I could fix it only by "unset DISPLAY".

Complete stacktrace is:


java.awt.AWTError: Can't connect to X11 window server using ':0' as the value of the DISPLAY variable.
at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
at sun.awt.X11GraphicsEnvironment.access$200(X11GraphicsEnvironment.java:65)
at sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:115)
at java.security.AccessController.doPrivileged(Native Method)
at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:74)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at java.awt.GraphicsEnvironment.createGE(GraphicsEnvironment.java:103)
at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:82)
at sun.awt.X11.XToolkit.<clinit>(XToolkit.java:126)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at java.awt.Toolkit$2.run(Toolkit.java:860)
at java.awt.Toolkit$2.run(Toolkit.java:855)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:854)
at java.awt.Desktop.isDesktopSupported(Desktop.java:169)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1850)
at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3758)
at org.codehaus.groovy.runtime.callsite.ClassMetaClassGetPropertySite.getProperty(ClassMetaClassGetPropertySite.java:51)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:296)
at org.codehaus.groovy.tools.shell.commands.DocCommand.<clinit>(DocCommand.groovy:57)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:247)
at org.codehaus.groovy.tools.shell.util.DefaultCommandsRegistrar.register(DefaultCommandsRegistrar.groovy:82)
at org.codehaus.groovy.tools.shell.util.DefaultCommandsRegistrar$register.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
at org.codehaus.groovy.tools.shell.Groovysh$_createDefaultRegistrar_closure3.doCall(Groovysh.groovy:116)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at org.codehaus.groovy.tools.shell.Groovysh.<init>(Groovysh.groovy:103)
at org.codehaus.groovy.tools.shell.Groovysh.<init>(Groovysh.groovy:122)
at org.codehaus.groovy.tools.shell.Groovysh.<init>(Groovysh.groovy:126)
at org.codehaus.groovy.tools.shell.Groovysh.<init>(Groovysh.groovy:130)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:247)
at org.codehaus.groovy.tools.shell.Main.<init>(Main.groovy:57)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:247)
at org.codehaus.groovy.tools.shell.Main.main(Main.groovy:151)





Sunday, September 15, 2013

Groovy: parse a file line by line, split, sort unique list of words

I know, in bash this would be a one liner... however when things become more complicated, your bash code becomes hell, while Groovy maintains its readability

print "Hello, welcome to the WordParser 1.0\n"

rootDir = "C:\\pierre\\downloads\\istdaseinmensch\\"
myfile = new File(rootDir + "Levi,_Primo_-_Ist_das_ein_Mensch.txt")

myWords = []
countWords = 0
countLines = 0

myfile.eachLine { line ->
 if (line.trim().size() == 0) {
  return null
 } else {
  countLines++
  words = line.split("[^A-Za-z0-9]+")
  for (theWord in words) {
      if (theWord.length() > 0 && !Character.isDigit(theWord.charAt(0))) {
 countWords++
 myWords.add(theWord.toLowerCase())
      }
  }
 }
}

print "countLines=" + countLines + " countWords=" + countWords + "\n"

myUniqueWords = myWords.unique().sort()

print "unique words = " + myUniqueWords.size() + "\n"

new File(rootDir + "out.txt").withWriter { out ->
 myUniqueWords.each {
  out.println(it)
 }
}




Next: how to invoke google translate REST API to get a translation for each word, and produce a readable output where each word has a mouse-over hint displaying its translation.
PS try doing this in Puppet, it will be ready by the end of time and meanwhile most of the functions you have used are no longer supported.

Friday, February 8, 2013

SOAPUI MockServices and Groovy Response

Suppose you have a request like this:


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <IdentifyCustomer>
         <WebIdentification>
            <Email>vernetto@yahoo.com</Email>
            <Password>ciao</Password>
         </WebIdentification>
      </IdentifyCustomer>
   </soapenv:Body>
</soapenv:Envelope>



and you must return this response whenever the email contains "@yahoo.com":

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <IdentifyCustomerResponse>
         <!--You have a CHOICE of the next 2 items at this level-->
         <IdentificationSuccessful>
            <MarketID>2</MarketID>
            <CustomerID>123456</CustomerID>
         </IdentificationSuccessful>
      </IdentifyCustomerResponse>
   </soapenv:Body>
</soapenv:Envelope>   


and this response whenever the email contains "@gmail.com":

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <IdentifyCustomerResponse>
         <IdentificationFailed>
            <ErrorCode>CUSTOMER_NOT_FOUND</ErrorCode>
            <ErrorDescription>we cannot find this customer</ErrorDescription>
         </IdentificationFailed>
      </IdentifyCustomerResponse>
   </soapenv:Body>
</soapenv:Envelope>


You can create a MockService and customize the MockResponse http://www.soapui.org/Getting-Started/mock-services/4-Customizing-a-MockResponse.html

this is the script:


def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder( mockRequest.requestContent ) 
def email = holder.getNodeValue("//Email")

if (email.contains("@yahoo.com")) {
 context.setProperty( "myresponse", "<IdentificationSuccessful><MarketID>2</MarketID><CustomerID>123456</CustomerID></IdentificationSuccessful>" )
}
else {
 context.setProperty( "myresponse", "<IdentificationFailed><ErrorCode>CUSTOMER_NOT_FOUND</ErrorCode><ErrorDescription>we cannot find this customer</ErrorDescription></IdentificationFailed>" )
}



and this the Groovy Response


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <IdentifyCustomerResponse>
  ${myresponse}
      </IdentifyCustomerResponse>
   </soapenv:Body>
</soapenv:Envelope>


Thursday, August 9, 2012

SOAPUI: groovy script to choose a different line in a file for each test iteration

We have a Property test step containing 2 properties:
Hostname and linecount
We initialize linecount to 0

At each iteration, this Groovy test step will assign to Hostname the next value from a file C:/pierre/workspace/SSS_AutomatedTests/SOAPUIArtifacts/hostnames.txt
Arrived at the end of the file, it will restart from the first line.

linecount= testRunner.testCase.testSteps["Properties"].getPropertyValue( "linecount" )
linecountInt = linecount.toInteger() + 1
//increment property linecount by one
testRunner.testCase.testSteps["Properties"].setPropertyValue( "linecount", String.valueOf(linecountInt) )

def myhostnamesFile = new File("C:/pierre/workspace/SSS_AutomatedTests/SOAPUIArtifacts/hostnames.txt")

//find number of lines in hostnames file
hostnamesinthefile = 0;
myhostnamesFile.eachLine { hostnamesinthefile++ }
log.info( "hostnames in the file: " + hostnamesinthefile)

//divide modulo
theLineNumber = (linecountInt % hostnamesinthefile) + 1
log.info("theLineNumber to choose=" + theLineNumber)
theHostnameToChoose = ""
//scan all lines, line contains the text and lineNo the line number starting from 1
myhostnamesFile.eachLine() { line, lineNo ->
 if ( lineNo == theLineNumber) 
  theHostnameToChoose = line
}

log.info( "theHostnameToChoose=" + theHostnameToChoose)

testRunner.testCase.testSteps["Properties"].setPropertyValue( "Hostname", theHostnameToChoose )



Monday, July 23, 2012

SOAPUI, setting dynamic properties with Groovy

I have a project POCO
and a Test Suite with a TestCase POCOTest

In the TestCase I create a Groovy Script step:


def project = context.testCase.testSuite.project
def tc = context.testCase
log.info project.name
log.info tc.name








see also:

http://www.soapui.org/Scripting-Properties/tips-a-tricks.html


Now, if I want to set a property, I have a choice of TestCase, TestSuite, Project or Global properties.

For instance, to set a new OrderID per each request:

import static java.util.UUID.randomUUID
def tc = context.testCase
uuid = randomUUID().toString()
testRunner.testCase.setPropertyValue( "OrderID", uuid )
log.info testRunner.testCase.getPropertyValue("OrderID")


After execution of this code (click the Run button in the Groovy Step editir), you have:





now you can add other steps AFTER the Groovy Step, and in the XML requests you can put

<ret:OrderUUID>${#TestCase#OrderID}</ret:OrderUUID>


All the Steps will share the same value of OrderID.



Thursday, July 12, 2012

SOAPUI and Groovy

Here the official doc, specifically the Property Expansion scripts.




your first script can be:
testRunner.runTestStepByName( "FindDescription" )


This PPT contains useful examples

Wednesday, November 2, 2011

Groovy: parsing XML with namespaces

99% of the examples on the Internet show how to parse XML without namespaces.

Unfortunately in real life 99% of the XML HAS namespaces :o(

Here is an example, the source XML is:

<?xml version="1.0" encoding="UTF-8"?>
<cus:Customizations xmlns:cus="http://www.bea.com/wli/config/customizations" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xt="http://www.bea.com/wli/config/xmltypes">
  <cus:customization xsi:type="cus:EnvValueCustomizationType">
    <cus:description/>
    <cus:envValueAssignments>
      <xt:envValueType>UDDI Auto Publish</xt:envValueType>
      <xt:location xsi:nil="true"/>
      <xt:owner>
        <xt:type>ProxyService</xt:type>
        <xt:path>OSBProject1/ProxyService1</xt:path>
      </xt:owner>
      <xt:value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">false</xt:value>
    </cus:envValueAssignments>
    <cus:envValueAssignments>
      <xt:envValueType>Service URI</xt:envValueType>
      <xt:location xsi:nil="true"/>
      <xt:owner>
        <xt:type>ProxyService</xt:type>
        <xt:path>OSBProject1/ProxyService1</xt:path>
      </xt:owner>
      <xt:value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">/OSBProject1/ProxyServicePippo</xt:value>
    </cus:envValueAssignments>
  </cus:customization>
  <cus:customization xsi:type="cus:FindAndReplaceCustomizationType">
    <cus:description/>
    <cus:query>
      <xt:resourceTypes>ProxyService</xt:resourceTypes>
      <xt:envValueTypes>UDDI Auto Publish</xt:envValueTypes>
      <xt:envValueTypes>Service URI</xt:envValueTypes>
      <xt:refsToSearch xsi:type="xt:ResourceRefType">
        <xt:type>ProxyService</xt:type>
        <xt:path>OSBProject1/ProxyService1</xt:path>
      </xt:refsToSearch>
      <xt:includeOnlyModifiedResources>false</xt:includeOnlyModifiedResources>
      <xt:searchString>Search String</xt:searchString>
      <xt:isCompleteMatch>false</xt:isCompleteMatch>
    </cus:query>
    <cus:replacement>Replacement String</cus:replacement>
  </cus:customization>
  <cus:customization xsi:type="cus:ReferenceCustomizationType">
    <cus:description/>
  </cus:customization>
</cus:Customizations>


The Groovy-XmlParser is:

def customizations = new XmlParser().parse("ALSBCustomizationFile.xml")
def cus = new groovy.xml.Namespace("http://www.bea.com/wli/config/customizations")
def xt = new groovy.xml.Namespace("http://www.bea.com/wli/config/xmltypes")
def xsi = new groovy.xml.Namespace("http://www.w3.org/2001/XMLSchema-instance")

customizations[cus.customization].each {
    if (it.attributes()[xsi.type] == 'cus:EnvValueCustomizationType') {
        println "FOUND!"
    }

    def values = it[cus.envValueAssignments][xt.envValueType]
    for (value in values) {
        print value
    }
}


Result:

FOUND!
{http://www.bea.com/wli/config/xmltypes}envValueType[attributes={}; value=[UDDI Auto Publish]]{http://www.bea.com/wli/config/xmlty
pes}envValueType[attributes={}; value=[Service URI]]


The Groovy-XmlSlurper way is:

def customizations = new XmlSlurper().parse("ALSBCustomizationFile.xml").declareNamespace(xt: 'http://www.bea.com/wli/config/xmltypes',xsi: 'http://www.w3.org/2001/XMLSchema-instance', cus : 'http://www.bea.com/wli/config/customizations')

println customizations

customizations.'cus:customization'.each {
    println "UNO"
 if (it.'@xsi:type' == "cus:EnvValueCustomizationType") {
  println "TROVATO"
 }
 
}


The very annoying difference between XmlParser and XmlSlurper is that in the first you use ns.part and in the other ns:part

java.lang.NoSuchMethodError: antlr/LexerSharedInputState.getTokenStartColumn()

If you get this error

java.lang.NoSuchMethodError: antlr/LexerSharedInputState.getTokenStartColumn()

when running Groovy from the CLI, be aware that you might have in the CLASSPATH some old antlr jars.

For instance, my CLASSPATH was:

echo %CLASSPATH%

C:\bea1035\patch_wls1035\profiles\default\sys_manifest_classpath\weblogic_patch.jar;C:\bea1035\patch_oepe1050\profiles\default\sys_manifest_classpath\weblogic_patch.jar;C:\bea1035\patch_ocp360\profiles\default\sys_manifest_classpath\weblogic_patch.jar;C:\bea1035\patch_jdev1111\profiles\default\sys_manifest_classpath\weblogic_patch.jar;C:\bea1035\JROCKI~1.2-4\lib\tools.jar;C:\bea1035\WLSERV~1.3\server\lib\weblogic_sp.jar;C:\bea1035\WLSERV~1.3\server\lib\weblogic.jar;C:\bea1035\modules\features\weblogic.server.modules_10.3.5.0.jar;C:\bea1035\WLSERV~1.3\server\lib\webservices.jar;C:\bea1035\modules\ORGAPA~1.1/lib/ant-all.jar;C:\bea1035\modules\NETSFA~1.0_1/lib/ant-contrib.jar;

If you do

set CLASSPATH=""

this should fix the problem, since groovy.bat will pick up the right CLASSPATH it needs to run.

Sunday, September 4, 2011

Groovy++ looks promising

http://code.google.com/p/groovypptest/wiki/Welcome

I love the syntactic terseness of Groovy, but I miss the solidity of Java type checking.

Groovy++ seems to bridge the 2 worlds. I will give it a try when I find the time (I need to break my leg and spend a month in hospital to find some time...)



Monday, August 1, 2011

Build path entry is missing: GROOVY_SUPPORT

in Eclipse, after installing the Groovy Plugin, I add library "Groovy Runtime Libraries" to my project:



If I define (Window/Preferences/Java/BuildPath/Classpath variables)

GROOVY_SUPPORT=C:/Oracle4/Middleware/oepe_11gR1PS3/plugins/org.codehaus.groovy_1.8.0.xx-20110627-1300-e36/lib/groovy-all-1.8.0.jar


all is fine, and my first test of embedding Groovy into Java works:

package com.pierre.osb;

import groovy.lang.Binding;
import groovy.lang.GroovyShell; 

public class GroovyCalloutTest {
 public static void main(String[] args) {
  GroovyCalloutTest test = new GroovyCalloutTest();
  test.run();
 }

 private void run() {
  // call groovy expressions from Java code
  Binding binding = new Binding();
  binding.setVariable("foo", new Integer(2));
  GroovyShell shell = new GroovyShell(binding);

  Object value = shell.evaluate("println 'Hello World!'; x = 123; return foo * 10");
  System.out.println("value=" + value);
  
 }
}



Groovy WSDL Parser

class PVWSDLParser {
 public static void main(String[] args) {
  PVWSDLParser parser = new PVWSDLParser();
  parser.parse("/path/to/your.wsdl");
 }
 
 public void parse(String filename) {
  
  def nsxsd = new groovy.xml.Namespace("http://www.w3.org/2001/XMLSchema", 'xsd')
  def nswsdl = new groovy.xml.Namespace("http://schemas.xmlsoap.org/wsdl/", 'wsdl')
  
  def wsdlDocument = new XmlParser().parse(new File(filename));
  def targetNamespace = wsdlDocument.'@targetNamespace';
  
  def imports = wsdlDocument[nswsdl.types][nsxsd.schema][nsxsd.import];
  imports.each { theimport ->
   System.out.println(theimport.'@schemaLocation');  
   System.out.println(theimport.'@namespace');
  } 
 }
}



A LOT easier than in Java!

Sunday, February 13, 2011

Small Groovy Script to filter a file

Groovy makes life sooo easy...

this small script prints only lines who do not start with file:///

I know it's much simpler in grep, but try doing something more complex with grep and awk and you will waste the entire day...


package com.pierre

datafile = new File('C:/pierre/download/myfile.txt') 
outdatafile = new File('C:/pierre/download/myfile.txt.out')
PrintWriter pw = new PrintWriter(outdatafile)

datafile.eachLine{ 
 line -> 
 if (!line.startsWith("file:///")) {
  pw.write(line)
  pw.write("\n") 
 } 
}


Monday, December 27, 2010

Groovy Callout in SOA Suite

I was musing about using Groovy to implement custom logic in SOA Suite.
I stumbled on this post covering Groovy with OSB.... interesting!

I have seen a gain of at least 300% in the mass of code produced with Groovy vs Java, so I am planning to use Groovy more often in future....

I am trying to build "complex" validation logic in Oracle Business Rules, surely you can do interesting stuff with this tool, but there is a learning curve and I am not sure how intuitive the code will be...

Friday, December 17, 2010

Groovy for Dummy Java Programmers (DJP) like me

http://www.infoq.com/presentations/Transforming-to-Groovy

this presentation by Venkat Subramaniam is quite cool.

Friday, September 17, 2010

Groovy for DSL

I am fed up of XML being used for the wrong thing (thank you Ant, Maven and the rest)
so I want to be able to design my own DSL.
I have the strong feeling that if you manage to design a DSL you gain a tool of immense power.

I wrote some 25 years ago a C compiler in Lex and Yacc, to be able to generate embedded firmware in Z80 controller cards, and it was great fun.
These days we have more powerful tools, like Groovy.

I am reading this book and I find it fascinating:

https://www.packtpub.com/groovy-for-domain-specific-languages-dsl/book



This link http://docs.codehaus.org/display/GROOVY/Writing+Domain-Specific+Languages  is also very dense of information.

Some concepts:
Java is cool, but verbose.
Groovy DSL is used internally by Groovy to implement parts of the Groovy framework.
An XML document is a primitive form of DSL
A DSL is a programming tool designed for the domain expert

..... to be continued...

This is a practical example on how to develop a Groovy DSL in minutes:
http://groovy.dzone.com/news/groovy-dsl-scratch-2-hours


and here a good presentation on Groovy DSLs

Sunday, September 12, 2010

Groovy: how to parse all property files in a directory

I also group the files by their suffix (dev2, dev3...)
and I print the property values, for names like admin_host, admin_port...


package com.acme.propertyprocessor
import java.io.File;


class PropertyProcessor {

    static main(args) {
        def envs = ["dev2", "dev3", "pp", "prod", "tst1", "tst2"];
        envs.each { env->
            println "

" + env + "

" new File("c:/properties").eachFile() { file-> if (file.getName().startsWith(env)) { def prop = new Properties() prop.load(new FileInputStream(file)) println prop.domain_prefix + " http://" + prop.admin_host + ":" + prop.admin_port + " http://" + prop.frontend_host + ":" + prop.frontend_port + " " + prop.ora_host1 + ":" + prop.ora_port + " " + prop.ora_user } } } } }


I suspect it could be made even simpler, for instance using eachFileMatch

Groovy rocks! Too bad I still haven't found a really professional IDE.

Sunday, August 8, 2010

WSDL Generation with Groovy

I am fed up of crafting WSDL by hand, it's mostly fluff and it can be generated from a template.

I don't like template languages like Velocity either.

So I have decided to generate my WSDL in Grovvy.

I have installed the Eclipse Plugin:
http://dist.springsource.org/release/GRECLIPSE/e3.5/

or
http://dist.springsource.org/release/GRECLIPSE/e3.6/



Here a good example of how to parse XML with Groovy:
http://groovy.codehaus.org/Reading+XML+using+Groovy%27s+XmlParser

The XML defining the service is:


GeoServicePS
1
../XSD/GEO_OSB_EJBSchema.xsd

 getCitiesByLikeCityName
 getLocationsByName
 getLocationsByLocationIds




First create a Groovy Project, then a Groovy class - this is only a POC on how to parse XML:


class WSDLGenerator {

 static main(args) {
  File file = new File("resources/geowsdl.xml");
  def records = new XmlParser().parseText(file.getText());
  def servicename = records.servicename.text();
  def version = records.version.text();
  def schemalocation = records.schemalocation.text();
  def operations = records.operations;
  for (operation in operations.operation) {
   println operation.text();
  }
 }
}



It's as simple as that! In Java it would have taken me 5 times more code!

I will never edit manually a WSDL again, all you need is a XSD with your domain model, and you can generate the blessed WSDL by script.