I'm trying to get the methods annotated with #XmlElement in the Top myxml but it the `myxml.methods[1]
import javax.xml.bind.annotation.*
import groovy.transform.*
import javax.xml.bind.*
#XmlRootElement
#XmlAccessorType(XmlAccessType.NONE)
#TupleConstructor
class Top {
String myBackingField
#XmlElement
public String getChildElement() {
return myBackingField
}
}
def myxml = new Top("child_one")
So far I got:
def mymethod = parsed.metaClass.methods.find { it.name == 'getChildElement' }
But the CachedMethod API doesn't give access to annotations.
From CachedMethod you can get to the java.lang.reflect.Method using CachedMethod.getCachedMethod() and from there you can use the Method.getAnnotations() or Method.isAnnotationPresent():
def mymethod = myxml.metaClass.methods.find { it.name == 'getChildElement' }
// mymethod.class is org.codehaus.groovy.reflection.CachedMethod
mymethod.cachedMethod.annotations // [#XmlElement(name=##default, namespace=##default,
// type=class XmlElement$DEFAULT, defaultValue=,
// required=false, nillable=false)]
To get only the methods with that annotation you can
def mymethods = myxml.metaClass.methods.findAll {
it.cachedMethod.isAnnotationPresent(XmlElement)
}
mymethods[0].class // CachedMethod backed by Method with XmlElement annotation
Related
I want to create a groovy's bean which takes the parameters of a request and return an appropriate response when the sum of parameter is positive. I want to know how I can load my request in a method of groovy bean
import com.eviware.soapui.support.XmlHolder
import com.eviware.soapui.support.GroovyUtils
import com.eviware.soapui.model.mock.*
import org.apache.commons.lang.StringUtils
import groovy.util.*
import groovy.lang.*
public class Test
{
public int somme ()
{
def holder = new XmlHolder(mockRequest.getRequestContent())
def a = holder["//firstInt:a"]
def b = holder["//secondInt:b"]
return(a + b)
}
public String getResponse ()
{
Test t = new Test ()
if (t.somme() > 0)
{
return "response1"
}
else
{
return "response2"
}
}
}
When I run this code I have error below:
com.eviware.soapui.impl.wsdl.mock.DispatchException: Failed to
dispatch using script; groovy.lang.MissingPropertyException: No such
property: mockRequest for class:Test
Your class is supposed to appear like this.
Note the changes:
Declared mockRequest member variable, pass it as argument to constructor of the class.
Object creation is not required in getResponse() method, instead you may do it in another script as you desired. Like in Mock response's script where mockRequest is available.
import com.eviware.soapui.model.mock.MockRequest
import com.eviware.soapui.support.XmlHolder
public class Test {
MockRequest mockRequest
public Test(MockRequest mockRequest) {
this.mockRequest=mockRequest
}
public int somme () {
def holder=new XmlHolder(mockRequest.getRequestContent())
def a=holder["//firstInt:a"]
def b=holder["//secondInt:b"]
(a + b)
}
public String getResponse () {
somme() ? "response1" : "response2"
}
}
I have the following two Groovy classes:
Buzz.groovy:
import widgets.Fizz
class Buzz {
def WhistleFeather
def init = { servletContext ->
WhistleFeather.load()
println "WhistleFeather loaded."
}
def destroy = { }
}
WhistleFeather.groovy:
package net.me.myapp
import widgets.Fizz
public class WhistleFeather {
def navMenu
def load() {
println "Loading!"
}
}
When execution gets to the WhistleFeather.load() method call I'm getting a NullPointerException. Can anyone see why?
WhistleFeather#load is an instance method, not a static method. Either call it with new WhistleFeather().load(), or turn it into a static method (static load() { ... }).
I created a java interface for my annotation. I am now writing a geb spock test and I would like to print the annotation values so it shows in the gradle report. Is this possible? Here is my test case and let me know if I am doing this wrong
class Checkout extends GebReportingSpec {
#TestCase(someID="12345")
def "A checkout 3-D script"() {
// My test steps.....
}
}
Use StackTraceUtils.sanitize to get the current method and use reflection to iterate through the annotations:
import java.lang.annotation.*
import org.codehaus.groovy.runtime.StackTraceUtils
class Checkout {
#TestCase(someID="12345")
def "yeah a"() {
printTestCaseId()
// My test steps.....
}
def printTestCaseId() {
def stack = StackTraceUtils.sanitize(new Throwable()).stackTrace[1]
def method = getClass().declaredMethods.find { it.name == stack.methodName }
println method
def someID = method.annotations[0].someID()
println someID
assert someID == "12345"
}
}
#Retention (RetentionPolicy.RUNTIME)
#interface TestCase { String someID() }
co = new Checkout()
co."${'yeah a'}"()
The StackTraceUtils is not needed if you are the one iterating through the methods.
spockframework (version "spock-core-1.1-groovy-2.4") is provides way of accessing annotation:
package com.test.integration.spec
import com.test.integration.annotation.Scenario
import com.test.integration.annotation.TestCase
import spock.lang.Specification
#Scenario("AnnotationSpec")
class AnnotationSpec extends Specification {
String scenario
String test_case
def setup() {
scenario = specificationContext.currentSpec.getAnnotation(Scenario).value()
test_case = specificationContext.currentFeature.featureMethod.getAnnotation(TestCase).value()
}
#TestCase("case-001")
def 'spock provides way of accessing annotation'(){
expect:
"AnnotationSpec" == scenario
"case-001" == test_case
}
}
I have a mixin class that bundles functionality for different types that do not share a common heritage. The mixing is applied using the #Mixin annotation, so it is handled at compile time.
Some of the mixin methods return this as the result of a method call. The problem is that the this is of the mixing type and not the type of the base class. When I want to work typed in the rest of the application a ClassCastException is thrown saying that the mixing type can not be cast to the base type.
In the example code below return this returns an object of type AMixin instead of an Object of type BaseClass.
How can I have return this return an object of type BaseClass instead of an object of type AMixin?
class AMixin {
def getWhatIWant(){
if(isWhatIwant){
return this
} else {
getChildWhatIWant()
}
}
def getChildWhatIWant(){
for (def child in childred) {
def whatIWant = child.getWhatIWant()
if (whatIWant) {
return whatIWant
}
}
return null
}
}
#Mixin(AMixin)
class BaseClass {
boolean isWhatiWant
List<baseClass> children
}
I just ran into this same situation. I solved it by setting 'this' from the concrete class into a private variable 'me' inside the concrete class and return 'me' in the Mixin classes. For example:
class MyMixin {
def mixinMethod() {
// do stuff
return me
}
}
#Mixin(MyMixin)
class MyConcreteClass {
private MyConcreteClass me
MyConcreteClass() {
me = this
}
}
I feel like it's a bit kludgy, but I think it's a lot simpler than this other solution. I personally need the ability to use the same Mixin in multiple classes, and it sounds like this other proposed solution would not allow for that if you cannot assign multiple Categories to a single Mixin class.
I created the class Base added the category to the AMixin Class and the BaseClass extends from Base.....(http://groovy.codehaus.org/Category+and+Mixin+transformations)
Executed this in GroovyConsole I get
BaseClass#39c931fb
class Base {
boolean isWhatIwant
List<BaseClass> children
}
#Category(Base)
class AMixin {
def getWhatIWant(){
if(isWhatIwant){
return this
} else {
getChildWhatIWant()
}
}
def getChildWhatIWant(){
for (def child in children) {
def whatIWant = child.getWhatIWant()
if (whatIWant) {
return whatIWant
}
}
return null
}
}
#Mixin(AMixin)
public class BaseClass extends Base {
}
def b = new BaseClass(isWhatIwant:true)
println b.getWhatIWant()
EDIT just a DummyClass. I know it's very awkward that It works....I'm sure Guillaume Laforge could answer how this works...
class DummyClass {
}
#Category(DummyClass)
class AMixin {
def getWhatIWant(){
if(isWhatIwant){
return this
} else {
getChildWhatIWant()
}
}
def getChildWhatIWant(){
for (def child in children) {
def whatIWant = child.getWhatIWant()
if (whatIWant) {
return whatIWant
}
}
return null
}
}
#Mixin(AMixin)
public class BaseClass extends DummyClass {
boolean isWhatIwant
List<BaseClass> children
}
def b = new BaseClass(isWhatIwant:true)
println b.getWhatIWant()
is there a convenient way to iterate Object's properties and to check annotations for each?
You can do it this way:
// First, declare your annotation
import java.lang.annotation.*
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface MyAnnot {
}
// Then, define your class with it's annotated Fields
class MyClass {
#MyAnnot String fielda
String fieldb
#MyAnnot String fieldc
}
// Then, we will write a method to take an object and an annotation class
// And we will return all properties of the object that define that annotation
def findAllPropertiesForClassWithAnotation( obj, annotClass ) {
obj.properties.findAll { prop ->
obj.getClass().declaredFields.find {
it.name == prop.key && annotClass in it.declaredAnnotations*.annotationType()
}
}
}
// Then, define an instance of our class
MyClass a = new MyClass( fielda:'tim', fieldb:'yates', fieldc:'stackoverflow' )
// And print the results of calling our method
println findAllPropertiesForClassWithAnotation( a, MyAnnot )
In this instance,this prints out:
[fielda:tim, fieldc:stackoverflow]
Hope it helps!