My program has two parts, one data structure and second operations.
Data Structure part is, basically and object & set of that object. This set is a class that extends ArrayList. Set and Objects are unique, what I mean is if I have a class named A then I have aSet which keeps the all A objects in it.
Operation part is doing some operations on those sets and most of the times it is also creates a new class in the runtime (write the class in a java file and compile it then call it from Reflect library functions e.g. constructor.newInstance(args);) and creates an object from new class then fill inside of it and return it. Since I didn't wanted to overwrite classes I use UUID trimmed for naming the new classes that created at the runtime.
I had noticed something odd. I run my code and it works, then I run it again and at the creation of set, it gives me "java.lang.IllegalArgumentException: wrong number of arguments". I run it again exception, again and again then I run it again then no exception. (Every time it created a new class like I wanted)
So why my code can act like this?
I am using Oracle Java 1.8 on Ubuntu 14.04 with Intellij Idea (tried also Eclipse no change).
Edit for code:
"I removed the codes unrelated to the problem"
And this is the part that gives error at my operation; (Initial innerInnerName is the random generated class name)
final String outerClassName = "" + initialInnerName + "Table";
final String innerClassName = "" + initialInnerName;
File file = new File("./src/");
URL url = file.toURI().toURL();
URL urls[] = new URL[]{url};
URLClassLoader loader1 = new URLClassLoader(urls);
Class<?> innerClass = loader1.loadClass(innerClassName);
Set<Template> newTable = null;
Class<?> outerClass = loader1.loadClass(outerClassName);
Constructor<?> constructorOfOuterClass = outerClass.getDeclaredConstructors()[0];
Object[] objArg = {innerClass,10};
newTable = (Set<Template>) constructorOfOuterClass.newInstance(objArg);
Edit 2
Exception being thrown at last line of last code which is:
newTable = (Set<Template>) constructorOfOuterClass.newInstance(objArg);
Well I had tried to do MCVE as much as possible.
Your "Outer Class" has two constructors, one that takes one argument and one that takes two. When you go to instantiate the outer class, you get the first in the list of constructors:
Constructor<?> constructorOfOuterClass = outerClass.getDeclaredConstructors()[0];
and then you try to invoke it with two arguments:
Object[] objArg = {innerClass,10};
newTable = (Set<Template>) constructorOfOuterClass.newInstance(objArg);
The problem is that the constructors aren't necessarily in the order you expect. No particular order is guaranteed, so sometimes you will get the one argument constructor and sometimes the two argument constructor. When you get the two argument constructor, all is well. But when you get the one argument constructor and invoke it with two arguments, well, you know all too well what happens then.
You need to determine which of the constructors is the one you want, and select it, rather than assuming that it is the first one in the list.
Related
I am creating my list like this and passing to a method withInitialListeners and then I don't see any compilation error and it works fine.
List<Host.StateListener> cassListener = new ArrayList<>(); // line 1
cassListener.add(new CassListener()); // // line 2
Builder clusterBuilder = Cluster.builder();
Cluster cluster =
clusterBuilder
.withInitialListeners(cassListener).build();
Now I was thinking to coming line1 and line2 in a single line and pass it directly to withInitialListeners method so I did something like this:
Builder clusterBuilder = Cluster.builder();
cluster =
clusterBuilder
.withInitialListeners(Arrays.asList(new CassListener())).build();
But with this approach it gives me compilation error as shown below:
The method withInitialListeners(Collection<Host.StateListener>) in the type Cluster.Builder is not applicable for the arguments (List<CassListener>)
What is wrong and how can I fix it? I am working with Java 7.
Ideally, you should change the signature of withInitialListeners to withInitialListeners(Collection<? extends Host.StateListener>).
If that is not an option, you can force the generic types of a method by placing explicit types in <…> before the method call:
Arrays.<Host.StateListener>asList(new CassListener())
As you can see, it’s pretty weird to write, and it may befuddle future developers who have to maintain it. The first option is preferred. But sometimes, explicit generic typing is unavoidable.
In a PreProcessor I am writing I can successfully update GET query string via sampler.
However if I use the same approach with POST, while I can list the FORM fields via getArguments(), the value does not get set.
Arguments arguments = sampler.getArguments();
for (int i=0; i<arguments.getArgumentCount(); i++) {
Argument argument = arguments.getArgument(i);
if (argument.getName().equals("page_submission_id")) {
String newVal = "8743718386872";
argument.setValue(newVal);
System.out.println("Setting arg["+argument.getName()+"] to["+newVal+"]");
}
}
sampler.setArguments(arguments);
printArgs(arguments);
The output from this shows Arguments values are unchanged.
Setting arg[page_submission_id] to[8743718386872]
Arguments After
...
Found arg[page_submission_id] is[XXXXXXXXXXXXX]
...
Having dug into the jmeter code a bit further, there is a "runningVersion" attribute of an Attribute object which (via isRunningVersion()) is set true.
I have tried a few ways to get round this:
force runningVersion to false - then values are set but a GET message is sent
create a new Arguments object and add new Argument entries to it with values - this does not change the values
Can anyone point out the official way to set POST FORM field values before they get sent?
Thanks
Well, you assigning a new value to an argument, but I fail to see where you updating sampler's arguments with the argument having the new value.
I'm a strong believer of KISS principle so instead of adding some more lines I would recommend simplifying your script as follows:
import org.apache.jmeter.config.Argument;
sampler.getArguments().removeArgument("page_submission_id");
sampler.addArgument("page_submission_id","8743718386872");
Also I hope you're using JSR223 PreProcessor and Groovy language.
I managed to resolve this:
(initially) by cleaning up the Thread Pool, as my initial
attempts had included a number of things like "Regular Expression
Extractors" and "User defined variables". Once those were removed
the approach I was using successfully changed the argument values, and
(when deeper in to my setup the problem came back) by adding the creation of a new Argments object and inserting (in the same order) new Argument objects with the value set as I require. Then setting the sampler to use that new Arguments object.
Arguments newArgs = new Arguments();
Arguments arguments = sampler.getArguments();
for (int i=0; i<arguments.getArgumentCount(); i++) {
Argument argument = arguments.getArgument(i);
HTTPArgument newArg = new HTTPArgument();
newArg.setName(arguments.getName());
if (arguments.getName().equals("field_to_replace")) {
newArg.setValue("new value");
}
else {
newArg.setValue(arguments.getValue());
}
newArgs.addArgument(newArg);
}
sampler.setArguments(newArgs);
My take is that this down to the "if (isRunningVersion())" test within setProperty() used by "Argument.setValue()" which I'm tripping over.
While this appears to work (for my test cases so far) I appreciate that overriding this may not be the correct formal approach.
I’m working on a program that utilizes evolutionary algorithms. This program was written prior to the introduction of Java generics. One of the many tasks I’ve been given is to remove the “raw type” warnings this legacy code is producing.
I’ve looked at several Java reference books and read all the answers to questions concerning the removal of these type warnings and haven’t found what I’m looking for. I can’t simply add the ? wildcard to the variable declarations to remove the warnings unless that is the only valid solution.
Here is an example snippet of code that is issuing warnings. Knowing what the contents of the three variables that are issuing the “raw type” warnings are going to be, how do I determine what to place inside the <> to eliminate the warnings?
Thanks in advance.
/**
* Uses the information from the configuration file to instantiate
* the right classes for the environment, statistics, algorithm slots
*/
private void reificate() {
try{
Raw type warning --> Class c = null;
Raw type warning --> Class params1 [] = new Class[1];
Raw type warning --> java.lang.reflect.Constructor cons = null;
Object [] params2 = new Object[1];
// Instantiating a configuration object
c = Class.forName(cfgSB.toString());
params1[0] = Class.forName("java.lang.String");
cons = c.getConstructor(params1);
params2[0] = new String(cfgFileName);
cfg = cons.newInstance(params2);
(The following code will require additional Class type variables to be declared, but if I can
learn how to eliminate the warnings above, I’ll know how to declare the new variables properly.)
// Instantiating an environment
c = Class.forName(envSB.toString());
params1[0] = Class.forName("jade.core.Config");
cons = c.getConstructors()[0];
params2[0] = cfg;
env = cons.newInstance(params2);
// Instantiating an Algo object to run
c = Class.forName(algSB.toString());
cons = c.getConstructors()[0];
params2[0] = cfg;
alg = (jade.core.EvolAlgo)cons.newInstance(params2);
// Creating statistics object and attaching it to cfg
// This has to be done last since statistics constructor is
// going to refer to the population of Algo via a local attribute C
c = Class.forName(staSB.toString());
cons = c.getConstructors()[0];
params2[0] = cfg;
sta = (jade.stats.Statistics)cons.newInstance(params2);
// ********************* end of snippet **************************//
Class.forName() returns Class<?>, see documentation.
It can't return a Class<String> even when you specify java.lang.String since there is no mapping between the string name and the actual class at compile time.
The same applies to constructors, parameters, .. You can only specify a concrete class type if you have a real runtime type (obtainable via String.class for example).
I'd do it roughly like:
jade.core.Config cfg = (jade.core.Config) Class.forName(cfgSB.toString())
.getConstructor(String.class)
.newInstance(cfgFileName);
// not sure what type that is..
Object env = Class.forName(envSB.toString())
.getConstructor(jade.core.Config.class)
.newInstance(cfg);
jade.core.EvolAlgo alg = (jade.core.EvolAlgo) Class.forName(algSB.toString)
.getConstructor(jade.core.Config.class)
.newInstance(cfg);
jade.stats.Statistics sta = (jade.stats.Statistics) Class.forName(staSB.toString())
.getConstructor(jade.core.Config.class)
.newInstance(cfg);
There is no need to create extra arrays, the methods take a comma separated list of things (varargs). You also don't need to specify forName("java.lang.String") since you can use the actual type here. And since you seem to know the type, you can use the getConstructor method instead of hoping that the first constructor is the correct one.
I instantiate a COM Object, then invoke a method.
ActiveXComponent comp = new ActiveXComponent("MyDll.MyClass");
String argument1 = "test1";
String argument2 = "test2";
Variant[] arguments = { new Variant(argument1), new Variant(argument2) };
comp.invoke("myMethod", arguments)
Assuming MyDll has a method called
myMethod(String s1, String s2)
it works fine.
Now, what if I have a Method
myMethod(String s1, ReturnDeletedModeEnum enum)
with an enum defined in MyDll?
I need to pass the enum to the method somehow, but I don't know how to access it.
I tried getting the Enum as ActiveXComponent,
new ActiveXComponent("MyDll.ReturnDeletedModeEnum");
which (not surprisingly) didn't work:
com.jacob.com.ComFailException: Can't get object clsid from progid
I tried finding some more documentation about Jacob, because there seem to be Enum-specific classes, but I haven't found any explanation on how to use them.
I ran into the same uncertainty when I needed to call a method with an Enummeration parameter. I couldn't find much documentation - JACOB or otherwise.
I did stumble across a helpful post on the subject which says the values ... correspond to internally stored numbers and An enumeration in VBA is always of data type Long.
Armed with that and the MS Documentation for my particular Enumeration, I gave this a try ...
Dispatch.call(oDocuments, "Open", fileIn, ... , new Variant(1L));
And it worked!
I'm sure there's a way to get actual "Enumeration" data structures, but this was good enough for me.
The situation seems to be abnormal, but I was asked to build serializer that will parse an object into string by concatenating results of "get" methods. The values should appear in the same order as their "get" equivalent is declared in source code file.
So, for example, we have
Class testBean1{
public String getValue1(){
return "value1";
}
public String getValue2(){
return "value2";
}
}
The result should be:
"value1 - value2"
An not
"value2 - value1"
It can't be done with Class object according to the documentation. But I wonder if I can find this information in "*.class" file or is it lost? If such data exists, maybe, someone knows a ready to use tool for that purpose? If such information can't be found, please, suggest the most professional way of achieving the goal. I thought about adding some kind of custom annotations to the getters of the class that should be serialized.
If you want that you have to parse the source code, not the byte code.
There are a number of libraries that parse a source file into a node tree, my favorite is the javaparser (hosted at code.google.com), which, in a slightly modified version, is also used by spring roo.
On the usage page you can find some samples. Basically you will want to use a Visitor that listens for MethodDefinitions.
Although reflection does not anymore (as of java 7 I think) give you the methods in the order in which they appear in the source code, the class file appears to still (as of Java 8) contain the methods in the order in which they appear in the source code.
So, you can parse the class file looking for method names and then sort the methods based on the file offset in which each method was found.
If you want to do it in a less hacky way you can use Javassist, which will give you the line number of each declared method, so you can sort methods by line number.
I don't think the information is retained.
JAXB, for example, has #XmlType(propOrder="field1, field2") where you define the order of the fields when they are serialized to xml. You can implemenet something similar
Edit: This works only on concrete classes (the class to inspect has its own .class file). I changed the code below to reflect this. Until diving deeper into the ClassFileAnalyzer library to work with classes directly instead of reading them from a temporary file this limitation exists.
Following approach works for me:
Download and import following libarary ClassFileAnalyzer
Add the following two static methods (Attention! getClussDump() needs a little modification for writing out the class file to a temporary file: I removed my code here because it's very special at this point):
public static String getClassDump(Class<?> c) throws Exception {
String classFileName = c.getSimpleName() + ".class";
URL resource = c.getResource(classFileName);
if (resource == null) {
throw new RuntimeException("Works only for concreate classes!");
}
String absolutePath = ...; // write to temp file and get absolute path
ClassFile classFile = new ClassFile(absolutePath);
classFile.parse();
Info infos = new Info(classFile, absolutePath);
StringBuffer infoBuffer = infos.getInfos();
return infoBuffer.toString();
}
public static <S extends List<Method>> S sortMethodsBySourceOrder(Class<?> c, S methods) throws Exception {
String classDump = getClassDump(c);
int index = classDump.indexOf("constant_pool_count:");
final String dump = classDump.substring(index);
Collections.sort(methods, new Comparator<Method>() {
public int compare(Method o1, Method o2) {
Integer i1 = Integer.valueOf(dump.indexOf(" " + o1.getName() + lineSeparator));
Integer i2 = Integer.valueOf(dump.indexOf(" " + o2.getName() + lineSeparator));
return i1.compareTo(i2);
}});
return methods;
}
Now you can call the sortMethodsBySourceOrder with any List of methods (because sorting arrays is not very comfortable) and you will get the list back sorted.
It works by looking at the class dumps constant pool which in turn can be determined by the library.
Greetz,
GHad
Write your custom annotation to store ordering data, then use Method.getAnnotation(Class annotationClass)