2

There is a third party java class in a library. Trying to extend that class in a Groovy Class. I would like to access that private property.

The problem is that it says

No such field: firstName for class: test2.Superuser

I am sure there must be a way to access the same and manipulate the property value using groovy.

Some posts suggests to use @ before property name in order to access private property. But no luck.

Here is the sample code snippets.

User.java (a third party class of a library)

package test;
class User {
  private String firstName;    
  private String name() {       
    firstName;    
  }
}

SuperUser.groovy (The one I am trying)

package test2

import test.User

class SuperUser extends User {
    public static void main(String[] args) {
       def suser = new SuperUser()
       suser.@firstName = "John"
       println suser.name()
    }
}

Any help is appreciated.

Using below versions:

groovy : 1.8.0
jdk    : 1.7.0
Rao
  • 20,781
  • 11
  • 57
  • 77
  • 1
    unfortunately I'm late to your question, I like to try to help people who really deserve it :) – albciff Nov 03 '16 at 17:31

3 Answers3

3

Java classes aren't able to access all of these private fields, properties and methods. It is only the other groovy scripts that are able to access it. The example below will demonstrate the same.

You should try to create both class file name as .groovy instead .java

User.groovy :

class User {

    private String firstName;
    private String name() {
        firstName;
    }
}

UserTest.groovy :-

class UserTest {
    public static void main(String[] args) {
        User user = new User();
        user.@firstName = "John"
        println user.name()
    }
}

Output :- John

It's working fine with Java 8 and groovy-all-2.4.3

Note:- Follow this link for more details

Edited :- If you don't want to change super class because of third party code, you should try using java reflection to access private property of a class.

Community
  • 1
  • 1
Saurabh Gaur
  • 23,507
  • 10
  • 54
  • 73
  • Thanks. Couple of things here to note, like it is mentioned in the question, I do not have the privilege to change the third party super class. And updated the question with the software versions and can't upgrade versions unfortunately. And also tried the code [here](https://groovyconsole.appspot.com/script/6217687118118912) which went futile. – Rao Sep 09 '16 at 14:30
  • Then you can't achieve this except try using reflection to make private to public forcefully then use. Thanks – Saurabh Gaur Sep 09 '16 at 14:33
  • Ok, Wondering if it can be done thru meta programming? – Rao Sep 09 '16 at 14:34
  • 1
    You can use reflection here to make private field to public forcefully then use – Saurabh Gaur Sep 09 '16 at 14:35
1

User.java is a Java class and not a Groovy class, so those variables are still private (unlike Groovy Variables which are always public to other Groovy classes).

So in the example above, unless the Java class includes some getters and setters, you will not be able to modify it's private members.

William Greenly
  • 3,914
  • 20
  • 18
  • Really not. Even if the super class is groovy (User.groovy instead of User.java), the behavior is same. – Rao Sep 09 '16 at 14:13
  • try without the @. Groovy access modifiers are a real mess and it kind of depends on your groovy version. – William Greenly Sep 09 '16 at 14:17
  • Using groovy 1.8 (which comes with soapUI 4.x). I did try that already, but did not help. Thank you for your time though. – Rao Sep 09 '16 at 14:19
1

Maybe I'm late, but with your Java and Groovy version you can do the follow using meta programming:

package test2

import test.User

class SuperUser extends User {
    public static void main(String[] args) {
       def suser = new SuperUser()
       User.metaClass.setProperty(suser,'firstName','John')
       println User.metaClass.getMetaMethod('name',null).invoke(suser,null)
    }
}

Or as other suggest in the traditional java reflection way:

package test2

import test.User

class SuperUser extends User {
    public static void main(String[] args) {
      def suser = new SuperUser()

      def firstNameField = SuperUser.superclass.getDeclaredField('firstName')
      firstNameField.setAccessible(true)
      firstNameField.set(suser,"John")

      def nameMethod = SuperUser.superclass.getDeclaredMethod('name')
      nameMethod.setAccessible(true)
      println nameMethod.invoke(suser,null)

    }
}
albciff
  • 18,112
  • 4
  • 64
  • 89
  • Some I could not update this later and ended up exactly the same using the link by saurabh. Thanks for your time for getting back. – Rao Nov 03 '16 at 17:44