Groovy call java method

Injecting methods at runtime to Java class in Groovy

I recently finished reading » Programming Groovy: Dynamic Productivity for the Java Developer » and this book really opened my eyes on what Groovy language really is. Most tutorials or lectures I have attended are focused on syntactical sugar: closures, operator overloading, easier access to bean properties or maps. Elvis operator, spread operator, spaceship operator.

But the strength of Groovy is not syntactic sugar on a Java cake. Groovy is a brand new dish with really exotic taste, which not everybody would enjoy. The gap between Java and Groovy is really huge, although they integrate tightly and seamlessly. But remember, Firefox did not became so popular because it was so similar to IE, but because it was different [1] . Maybe Groovy is not better than Java, but is certainly worth trying. Thanks to » Programming Groovy. » I realized what amazing things can be done using Groovy which you would never even thought about in Java.

As Chinese said, Java code is worth more than a thousand words (or something like that. ), I’ll give you some short example announced in post title. Suppose you have some POJO:

public class Person private String name; 
private Calendar dateOfBirth;
private BigDecimal salary;

public String getName() return name;
>

public void setName(String name) this.name = name;
>

public Calendar getDateOfBirth() return dateOfBirth;
>

public void setDateOfBirth(Calendar dateOfBirth) this.dateOfBirth = dateOfBirth;
>

public BigDecimal getSalary() return salary;
>

public void setSalary(BigDecimal salary) this.salary = salary;
>
>

Yes, this is Java class, remember that. Our task is to create simple validator, which will check whether all properties are not-null of a particular Java Bean instance (e.g Person ). If any null field found, exception should be thrown.

Читайте также:  Цвета

Doing this in the classic way, you would write some sort of utility class with method like:

public static void validate(Object pojo) throws IllegalStateException 

This approach is so obvious, that I won’t even explain this API. Behind the scenes some nasty reflection with tons of exception handling and method name parsing code will be used to make the method generic. If you are clever, you would use Commons-BeanUtils. But this is still poor object-oriented design, as data (properties of a JavaBean) and operations ( validate() method operating on data) are separated. Wouldn’t it be great to have validate() method in Person and every other bean you wish? To achieve this, you would probably think about inheritance and placing validate() in some abstract base class of all your Java Beans.

No, stop that! This is still bad design, although much more subtle. Inheritance represents is-a relationship. If you want to use the same operation in many objects, you should rather use delegation. See «Replace Inheritance with Delegation» chapter in Fowler’s «Refactoring: improving the design of existing code» (I know, I know, some parts of the book are not so outdated :-)). But if you are not so sensitive about code design (why. ), there is another problem – this approach cannot be applied to third-party classes, which you are not allowed to change.

This is the place where Groovy comes in with its amazing dynamic capabilities. First I will prepare some Groovy test case, which will explain what I am trying to achieve. Test-driven development, anybody?

public class PersonTest extends GroovyTestCase 
void testAllPropertiesNullShouldThrow() def person = new Person();
shouldFail(IllegalStateException)
>

void testSingleNullPropertyShouldThrow() def person = new Person(name: "John Smith", salary: 1234d)
shouldFail(IllegalStateException)
>

void testAllPropertiesSetShouldNotThrow() def person = new Person(name: "John Smith", dateOfBirth: Calendar.instance, salary: 1234d)
person.validate()
>

>

Read those tests carefully. Not because I use elegant shouldFail() template nor very concise way of initializing POJO (even though it does not have any non-default constructor!) The most surprising fact is that I run validate() method on Person class instance and the code compiles just fine! It doesn’t matter this method does not exist on compile time, even if it is Java object. Groovy’s dynamic. But what happen if I run this test?

groovy.lang.MissingMethodException: No signature of method: Person.validate() is applicable for argument types: () values: []at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:54)
at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:46)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:121)
at PersonTest.testAllPropertiesSetShouldNotThrow(PersonTest.groovy:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)

Surely, Person Java class does not have validate() method, even if Groovy compiler assumed differently. So you might ask yourself, what is the purpose of such a weak compilation? Well, now comes the best part:

void setUp() Person.metaClass.validate =  
delegate.properties.each
if (value == null)
throw new java.lang.IllegalStateException("Property $property is null")
>
>
>

What I’ve done here is I injected method called validate() to meta class of Person Java class at runtime. Since now, every instance of Person class is capable of handling validate() method even though this method has not been known during compilation. Quick test case execution and. success, not only the method is known, but it works as expected.

I won’t discuss details of validate() implementation, simply try to rewrite it in Java, you’ll see the difference. But it is not the point! I created brand new method and applied it to arbitrary Java class (of course, if Person was Groovy class, it would work as well). This is absolutely impossible in static Java. And if I add that by implementing methodMissing() object could handle ANY nonexistent method call.

You might ask yourself once again, what is the purpose of such a dangerous and unpredictable toy? Well, I am about to obtain «The Definitive Guide to Grails»*, which also explains GORM framework. If you would like to make Person class persistent, Groovy ORM will automatically inject save() method to Person class, so you could write:

new Person(name: "John Smith").save()

No DAO, no session, na EntityManager . But you could also write:

def list = Person.findByNameLikeAndSalaryGreaterThan("John%", 1000)

Where is the implementation of this not-so-simple method? You don’t have to implement it, Groovy will! It will discover that such a method does not exist in Person class, parse the name and create proper SQL with AND and LIKE operators on Person table, issue SQL and map to a list of Person instances. If this is not magic, go back to your Hibernate, as I find such features absolutely exciting and innovative.

I am just playing with Groovy, but I found this language to have many unexpectedly interesting parts. It is not a replacement of Java, but a great tool to combine and interact with its older brother.

* many thanks to my employer for sponsoring aforementioned books

Be the first to listen to new episodes!

To get exclusive content:

  • Transcripts
  • Unedited, longer content
  • More extra materials to learn
  • Your user voice ideas are prioritized

Источник

[Solved]-How to call java method in groovy-Java

Groovy uses the JVM and uses java classes normally. If you look in the $GROOVY_HOME/lib directory you’ll see there are jar files there, many of which were built from java code.

Add a jar to the classpath and groovy can see its classes (use import to specify what classes you want, exactly like with java). You can also drop jars into $GROOVY_HOME/lib if you want to make them available to groovyconsole or groovysh.

  • How to call a method on program start from Java library?
  • How to call a method from a different class in a java project
  • How to call a method from a certain Java thread
  • How do i call a Spring Java method annotated with @Component?
  • How to call the method & fix error in this Java code?
  • how to use an object (constructor) to call display() method in processing using java on visual studio code while importing PApplet
  • How to extract information from Java stack as individual data types and use in method call
  • How to call java method in xml attribute
  • Java — how to call a method of corresponding class based on string using enum/factory pattern
  • How to call a custom method after Mapreduce Job completition using Hadoop java api?
  • How to call java class and its method from JNI android?
  • How to call Java method (custom class) with an interface typed parameter in Nativescript
  • Groovy — How to see java method System.out.println
  • How to properly call a method in java from another class if they are in a composition?
  • How do I make a java client to call a soap WebService method with parameters?
  • JNA how call a method from java in an Pointer received from dll?
  • How to call the hidden Android method getTotalUss() using Java reflection?
  • How to call method of python file using java
  • How to call and run java class method in my jsp file
  • Unable to call Java Method from Groovy Script within SOAP UI
  • Cocos-Code-IDE- How to call java method in cocos2dx using lua language
  • How can I call a method with requestParameterMap from other controller
  • Java: How can I recursively call my method with an original param in the recursive call
  • How to avoid actual method call while running through junit test case
  • How can I create a method in Java that rotates an image 90 degrees clockwise?
  • How to know if the method is static using java instrumentation and ASM
  • How do I properly call a method inside a method inside the same class?
  • How can I call Java applet methods with Javascript?
  • how to call the onDraw method of a SurfaceView using a thread class
  • Groovy CodeVisitorSupport Call Method

More Query from same tag

  • Commons email example hanging on send()
  • jpa many-to-many with additional column
  • Using Nailgun in Eclipse for Java and Jython
  • How to monitor state of Java applications running on different machines using zookeeper?
  • command to test all unit tests for java gitlab CI/CD
  • How can I print a line of text on the same line as a for-loop output
  • Web application in jsp/servlets — localization using fmt:message
  • Eclipse/STS auto-correcting «new» as «newEmail»
  • NPE when POSTing Binary data to RESTEasy Service
  • How to practically make a bridge between user interface and the RFID reader/KOHA database? in java
  • Extending and returning values over classes
  • Access super class property without using super
  • In Android Using Zxing scanner how to read UPI QR code?
  • Java 11 XML parser pauses and displays entity error when calling normalizeDocument() on XHTML 1.1 document
  • Hibernate Session Factory Android
  • Tomcat stopped working suddenly on production server
  • Beans inside beans in SpringFramework?
  • Time limit on recursive methods in java
  • Jersey 2.x add multiple headers to ClientConfig
  • java program to copy files from/to mobile device
  • Elastic search give priority to starts with match
  • setting maxHttpHeaderSize attribute tomcat maven plugin
  • Find if long string of chars contains any patterns
  • byte[] encodeBase64(byte[] binaryData) equvalent in c#
  • Karate : In my CSV file, columns are not having same row count. While reading data empty values are added for columns having less rows
  • How to navigate websites using Jsoup in java
  • java.text.ParseException: Unparseable date: «-«
  • Batch for loop to execute java — how to dereference variable as part of command
  • LDAP Date Search Filter
  • eclipse swt ExpandBar: wrong size on expand/collaps events

Источник

Оцените статью