MyClass has a setter but when I assign a value to it I get the error:
java.lang.NoSuchMethodError: MyClass.setValue(Ljava/lang/String;)
MyClassIfc.java
public interface MyClassIfc extends EYSDomainIfc
{
public abstract String getValue();
public abstract void setValue(String paramString);
}
MyClass.java
public class MyClass implements MyClassIfc
{
protected String value = null;
public String getValue()
{
return this.value;
}
public void setValue(String paramString)
{
this.value= paramString;
}
}
Invoking sipnet:
MyClassIfc myClass = ((MyDomainObjectFactoryIfc)MyDomain.getFactory()).getMyInstance();
value = MyUtilities.getValue(utility, data, logger, serviceName);
myClass.setValue(value);
This means that you're trying to run a different version of that class from the one that you used at compile time. Clean out your build directories and recompile everything.
Can you share the code you did write in your class? Whenever you get NoSuchMethod the first thing you'd like to look at is the method signature.
For example:
Modifiers—such as public, private, etc: Make sure you get access modifier right, if you are calling the method creating an instance of the class (an object) and that method is private you won't be able to access it.
The method name: take a closer look to the method name and make sure you are typing it correctly. If you are using an IDE just let the autocomplete help you to avoid errors.
The parameter list their data types: Make sure the data-type of the variable/object you are passing to the method matches the datatype that the method has declared (what the method is expecting).
In your case, I would go for the parameter list first.
If you want to read more about method definition you can go to the java reference: http://docs.oracle.com/javase/tutorial/java/javaOO/methods.html
Hope this helps!
Related
I have a method let's say in ClassA. I want to pass a method from ClassB as an argument to that method in ClassA. In this case I want to pass the getCode method from ClassB. I don't have any instance of ClassB and I'd like to achieve this without having to create one.
I've tried using simple method reference, but it does not work this way.
I don't want to make getCode a static method either.
public class ClassA {
public void validate() {
Validation validation = new Validation(ClassB::getCode, code);
//...
}
}
My final goal is to have a RequestValidator class to which add validations, each validation will be created with a specific method and a string in its constructor, in this case getCode from classB and code. Please note I only want one instance of RequestValidator. Something like this:
RequestValidator validator = new RequestValidator<>()
.addValidation(new Validation(ClassB::getCode, code))
.addValidation(new Validation(ClassB::getName, name));
getCode needs to be a static function, and the syntax would be ClassB.getCode. You would need ClassB to be imported into ClassA.
See:
Calling static method from another java class
Your use of a method reference will work just fine as long as you define the method arguments properly. You haven't given a lot of information, so I'm going to make some assumptions here. Please correct me if this isn't what you had in mind:
public class B {
public static String getCode() {
return "foobar"; // Replace with your own functionality
}
}
public class Validation {
Validation(Supplier<String> supplier, String code) {
String suppliedCode = supplier.get();
// Do your validation logic
}
}
public static void validate() {
Validation validation = new Validation(ClassB::getCode, code);
}
But this frankly feels like overkill. Why can't you just make your Validation constructor take two String arguments (or whatever types you happen to be using), and then do this?
public static void validate() {
Validation validation = new Validation(ClassB.getCode(), code);
}
Do you have a legitimate need to pass in a method reference instead of simply passing in the return value from the method call?
I'am trying to make a OGM to translate object to Vertex for the OrientDB. Currently i'am using GCLib but i read that ByteBuddy could implements two critical things that if work, it will improve the OGM speed.
Could ByteBuddy implement field access control? I read the doc but it's not clear or I do not understand it.
Dinamically add default empty constructor.
The current problem is this: We do not know the class definition that will be passed as a parameter. The idea is to redefine the class and implement the empty constructor if it not have one, add a field named __BB__Dirty to set the object as dirty if an assign operation was detected and force the implementation of an interface to talk with the object.
Example:
A generic class:
public class Example {
int i = 0;
String stringField;
public Example(Strinf s) {
stringField = s;
}
public void addToI(){
i++;
}
}
Now we have an interface like this:
public interface DirtyCheck {
public boolean isDirty();
}
So, I want to force the Example class to implement the interface, the method isDirty(), a field to work on and a default contructor so the class should be translated to:
public class Example implements DirtyCheck {
int i = 0;
String stringField;
boolean __BB__dirty = false;
public Example() {
}
public Example(Strinf s) {
stringField = s;
}
public void addToI(){
i++;
}
public boolean isDirty() {
return this.__BB__dirty;
}
}
and the some magically assigner so if any field (except __BB__dirty) is modified, the __BB__dirty field is set to True;
I have tried the first part of this but I fail :(
...
ByteBuddyAgent.install();
Example ex = new ByteBuddy()
.redefine(Example.class)
.defineField("__BB__Dirty", boolean.class, Visibility.PUBLIC)
.make()
.load(Example.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent())
.getLoaded().newInstance();
....
ex.addToI(); // <--- this should set __BB__dirty to true since it
// assign a value to i.
But i get this error:
Exception in thread "main" java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)
at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
at sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:170)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Strategy$1.apply(ClassReloadingStrategy.java:297)
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy.load(ClassReloadingStrategy.java:173)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:4350)
at Test.TestBB.<init>(TestBB.java:33)
at Test.TestBB.main(TestBB.java:23)
I'am stuck in the very first stage to solve the problem with BB.
Thanks
The Java virtual machine does not support changing the layout of classes that are already loaded when redefining a class. This is not a limitation of Byte Buddy but the VM implementation.
In order to do what you want, you should look at the AgentBuilder API which allows you to modify classes before they are loaded. Creating an agent does however require you to add it explicitly as an agent on startup (opposed to adding the library to the class path.
You can implement the interface by calling:
.implement(DirtyCheck.class).intercept(FieldAccessor.of("__dirty__");
You can also add a default constructor by simply defining one:
.defineConstructor(Visibility.PUBLIC).intercept(SuperMethodCall.INSTANCE)
The latter definition requires the super class to define a default constructor.
Say that i have a boolean property that should represent the fact that a specific file inside a specific path exists or not.
Here is some code:
class SomeClass {
protected static final File FILE_TO_TEST = new File("test.canc.me");
//My javafx property
public ReadOnlyBooleanPropertyBase fileExistingProperty = new ReadOnlyBooleanPropertyBase() {
#Override public boolean get() {
return FILE_TO_TEST.exists();
}
#Override public Object getBean() { return null; }
#Override public String getName() { return ""; }
};
//old style property property
public boolean isFileExisting() {
return fileExistingProperty.get();
}
Ok. The fact is that this property is read only since it cannot be set, its value depends of the "external" condition represented by the file to be existent in the application home.
Yet, i need to refresh the property, that is look again to see if the file still exsist or not, and raise change and invalidation events accordingly.
I could easily add a refresh method to the property class, but in order to call it, i would have to create an inner class and not just an anonyous one.
And i would need an anonymous class for each different type of read-only-yet-refreshable property, that is boolean, String, Integer etc.
The question is: is there a more convenient way to accomplish this?
i would have to create an inner class and not just an anonyous one.
I would go down this approach rather than try to create a bunch of anonymous inner classes.
And i would need an anonymous class for each different type of read-only-yet-refreshable property, that is boolean, String, Integer etc.
Use generics - that's what they're designed for! Create a ReadOnlyRefreshableProperty<T>, then the return types and parameters of the relevant methods all use T as their type, removing the need for a separate class for each type.
I wanted to try the factory pattern and was able to implement it, but when
generating for more than a few classes, i thought this will be ugly!! so any clarity or suggestions would be really appreciated...
My Superclass:
public abstract class Output {
public abstract void generate(Data dat); }
i got my other classes extending from Output like
public class generateXML extends Output{
.
.
.
}
My question is related to here:
public class generatorFactory(){
public Output generate(String str){
// or getting an Object as an argument like (Object obj)
if(str.equals("xml"){
return new generateXML();
}
else if.........
......
}
Is there any way we can determine the subclass type avoiding checking for each type??
You should consider replacing your if-else chain with a map.
Rather than having to write the code that checks for all the strings you want to support you just have a copule of lines to retrieve the element from the map.
You will, of course, need some more configuration code to put the items in the map, but that should be trivial.
Here it is a nice post about this topic (in PHP)
You can use newInstance() to instanciate a generator whose classname you've built from the parameter:
public Generator getGenerator (final String type)
{
final Class generatorClass = ClassLoader.getSystemClassLoader().loadClass("Generator"+type);
final Generator generator = (Generator) (generatorClass.newInstance());
return generator;
}
PS: I highly rate you to follow the rules of Java: if generateXML is a class, it should be written GenerateXML.
More over: take care by naming your classes. (1) An Object generateXML shouln'd extend Output, because it isnt' an output. (2) "GenerateXML" is a verb, i.e. an action. It is therefore not a correct word to name an object, but a method. You could name the object per example "XMLGenerator".
You can use Reflection.
Object generated = getClass().getMethod("generate" + type.toUpperCase()).invoke(this);
public Object generateXML();
public Object generateJSON();
public Object generateCSV();
You can use enum which can be passed to factory and return factory object based on enum passed. The only thing is you can not export it as API.
enum Type
{
XML {
#Override
public Object getFactory() {
// TODO Auto-generated method stub
return null;
}
};
public abstract Object getFactory();
}
If you have to expose it like API then you can do something like below.
interface IType {
public abstract Object getTypeFactory();
}
enum Type implements IType {
XML {
#Override
public Object getTypeFactory() {
// TODO Auto-generated method stub
return null;
}
};
}
And change Factory method implemetation to
public static Object getFactoryByType(String name) {
Type type = Type.valueOf(name);
return type.getTypeFactory();
}
Since you have to call new everytime I'm not sure you can bypass the branching process. Someone has to know what to give you back.
If it was for singletons you could initialize an HashMap "xml"=>generateXML singleton
After second though, you may modify your String attribute for differents Type classes MyTypeXML, MyTypeJSON, ...
and then use method with the same name but different type.
public Output generate(MyTypeXML xml) { // This will go for XML }
public Output generate(MyTypeJSON json) { // This will go for JSON }
But for factories, I'm not really against the if...else coding.
Hey I'm trying to write a function that calls a static function based upon its generic arguments.
I'm having the following code:
public class Model<T extends Listable>
{
private Document doc;
/*
When the JavaBean is created, a Document object is made using
the Listable parameter. The request string for the specific
type is used to pull XML-data from the cloud.
*/
public Model()
{
try
{
doc = cloud.request(T.getRequestString());
}
catch(Exception e)
{
}
}
/*
getMatches (used in JSP as "foo.matches") generates a list
of objects implementing the Listable interface.
*/
public List<Listable> getMatches()
{
return T.generateMatches(doc);
}
}
How do I do this, I'm just getting something about static contexts.
'non-static method generateMatches(org.jdom.Document) cannot be referenced from a static context'
Turned comment into answer:
You can introduce an instance variable of type T and call generateMatches on that. You cannot call generateMatches on the type T itself.
You could e.g. inject this instance variable via the constructor and store it in a private variable:
private T instanceOfT;
public Model(T instanceOfT){
this.instanceOfT= instanceOfT;
}
In your getMatches method you can then do this:
return instanceOfT.generateMatches(doc);
Your problem is that you do not have handle to any object of class T. Just saying T.generateMatches(doc) means you are making a static call to static method in class T. You need to have a variable of type T to call instance methods.
What's the question ?
The reason is clear - the line "T.generateMatches(doc);" calls generateMatches through T, and T is type (class/interface), not instance.