I have to implement some classes in Java that will pass tests written in C# (using Visual Studio unit tests). I came across problem with this part of test:
var portfolioSignatureAttribute = dllType
.GetCustomAttributes(typeof(SignatureAttribute), false)
.Cast<SignatureAttribute>()
.FirstOrDefault();
Assert.AreEqual("<C::LIConverter<LCurrency;LCurrency;>;>Ljava/util/ArrayList<LBoughtStock;>;Ljava/lang/Iterable<LBoughtStock;>;", portfolioSignatureAttribute.Signature, iterableMessage);
The signature I tried writing was, but doesn't work is:
public class Portfolio extends ArrayList<BoughtStock> implements IConverter<Currency, Currency>, Iterable<BoughtStock>
Also, i got some message thrown by this assertion:
Type Portfolio incorrect signature. Remember to add generic interface java.lang.Iterable implementation. Remember to give a name C to generic parameter. Remember also to inherit your class from java.util.ArrayList.
And here is also fragment from test output:
Result Message: Assert.AreEqual failed.
Expected:<<C::LIConverter<LCurrency;LCurrency;>;>Ljava/util/ArrayList<LBoughtStock;>;Ljava/lang/Iterable<LBoughtStock;>;>.
Actual:<Ljava/util/ArrayList<LBoughtStock;>;LIConverter<LCurrency;LCurrency;>;Ljava/lang/Iterable<LBoughtStock;>;>.
So generally, there is problem with: lack of "C::" and with order of those attributes. I totally cannot find anywhere any informations about such things, and how to understand it. And the question is - what the class signature should be?
Thanks for help!
I managed to solve the problem (by myself, i am proud :) )
The signature should be:
public class Portfolio<C extends IConverter<Currency, Currency>> extends ArrayList<BoughtStock> implements Iterable<BoughtStock> {
Related
trying to use in java class defined in scala library.
Definition:
final class ScenarioBuilder(...) extends StructureBuilder[ScenarioBuilder]
trait StructureBuilder[B <: StructureBuilder[B]] extends Execs[B] with Feeds[B]
yes, it is Gatling.
my java code:
public ScenarioBuilder callMyApi(ScenarioBuilder in) {
return in.feed(myFeeder.asScala())
.exec(addCookie(Cookie("key", "value")).asScala())
.exec( http("my api call")
.get("/api").asScala());
}
Idea finds this code correct, but whenever i try to compile it i get this errors:
symbol: method exec(io.gatling.core.action.builder.ActionBuilder)
location: class java.lang.Object
or
java: incompatible types: java.lang.Object cannot be converted to io.gatling.core.structure.ScenarioBuilder
in other words methods B feed(...) from Feeds[B] and B exec(...) from Execs[B] always return Object and i would expect B to be ScenarioBuilder
the only way to compile and run this code i came up with is this:
public ScenarioBuilder callMyApi(ScenarioBuilder in) {
StructureBuilder<ScenarioBuilder> sb = in;
sb = (StructureBuilder<ScenarioBuilder>) sb.feed(myFeeder.asScala())
.exec(addCookie(Cookie("key", "value")).asScala());
return (ScenarioBuilder) sb.exec( http("my api call")
.get("/api").asScala());
}
and it looks disgusting
questions:
why does java misses generic info from scala classes?
is there better way to utilise scala Gatling api in java?
why does IDE finds the first variant correct and compiler does not?
yes, i know there's java api in Gatling though by some reason method make is defined like this:
public ScenarioBuilder make(
Function<io.gatling.core.structure.ScenarioBuilder, io.gatling.core.structure.ScenarioBuilder>
f) {
return new ScenarioBuilder(f.apply(wrapped));
}
and to me it is very open question why it is defined this way.
thanks in advance
UPD:
java- 1.8, scala- 2.11.8
myFeeder = listFeeder(Arrays.asList(
Collections.singletonMap("items", Arrays.asList("Item 1", "Item 2"))
)).circular()
Gatling version - 3.9.0 though the question not about Gatling itself it is mostly about calling scala code with generics from java.
By some reason javac does not see generic info in scala classes, and i wonder why.
As to Gatling i've solved the issue by proper API usage, long story short don't use make methods for construction scenario from different steps exec(ChainBuilder) is the choice.
Disclaimer: Gatling's author here
is there better way to utilise scala Gatling api in java?
Don't. Gatling's Java DSL wasn't built with interoperability with the Scala DSL in mind. In particular, asScala() is an internal.
Go with either one or the other, but don't mix them together.
It is possible to use ScalaTest in a Java test file, and if so where can I find examples?
When I try something like:
// MyUTest.java
import org.scalatest.flatspec.AnyFlatSpec;
import org.scalatest.matchers.should.Matchers;
public class MyUTest extends AnyFlatSpec, Matchers {
...
}
I get an error that equal(Object) in Matchers clashes with the same method in matchers.dsl.MatherWords
TL;DR: You cannot do what you are trying.
As stated in Using Scala traits with implemented methods in Java:
From Java perspective Trait.scala is compiled into Trait interface. Hence implementing Trait in Java is interpreted as implementing an interface - which makes your error messages obvious. Short answer: you can't take advantage of trait implementations in Java, because this would enable multiple inheritance in Java (!)
and Matchers is a trait. However, to overcome this issue, you can just remove the Matchers extension, and have the test class:
import org.scalatest.flatspec.AnyFlatSpec;
public class MyUTest extends AnyFlatSpec {
}
Which will compile. Having said that, it will be really hard to actually use the the ScalaTest functionality in Java. For example, a simple test class will be:
public class MyUTest extends AnyFlatSpec {
it should "test1" in { println("test1") }
}
The word should above, is declared at AnyFlatSpecLike, which is trait as well. So you cannot really use it. So I am not really sure how you can overcome this issue, as this is the very basic example that you can find in ScalaTest quick start.
After the above analysis, I think it's going to be really difficult to use ScalaTest in Java. What you can easily do, is the other way around. If you already support Scala, and you have ScalaTest, you can just test the java code in Scala. It is a bit less "organized" as you'd expect to see the java test classes under the java folder, which we just proved impossible. I think having this "mess" is the best solution in such structure.
I totally agree with #Tomer Shetah. I would like to add that you can create wrapper for java on scala:
class JavaScalaTestWrapper extends AnyFunSpec with Matchers {
def println(x : scala.Any) = Predef.println(x)
def shouldEqual(x : scala.Int, ) = SomeCode.someFunc(x) shouldBe s"${x}"
}
And after that you can extend all java test classes through this wrapper:
public class SomeOperationTestJava extends JavaScalaTestWrapper {
#Test
void someOperation() {
SomeOperation so = new SomeOperation();
println("=== test ===");
assert(("test").equals(so.someOperation()));
shouldEqual(3);
}
}
And all scala styled code you can put in wrapper, and after that use these methods from original java code, like additional workaround.
I am relatively new (ish) to Java..
I am writing an Android app, and now I am going back over my code and tidying up and adhering my coding structure to a more best practice style.
I am building methods and classes as I see fit to avoid the numerous amounts of duplicate code that I have produced. I have found myself trying to create a class (e.g. HeavyStuff.java) that contains several AsyncTask methods inside it (e.g. MyTask1 and MyTask2). When calling the class from an activity, I'd like to execute MyTask1 at some point, and at some point elsewhere I'd like to execute MyTask2. I am trying to use the following respectively:
HeavyStuff.MyTask1 myTask1 = new HeavyStuff.MyTask1();
myTask1.execute();
And
HeavyStuff.MyTask2 myTask2 = new HeavyStuff.MyTask2();
myTask2.execute();
The problem is, I get an error saying that "HeavyTest is not an enclosing class". My class looks like this:
package com.wizzkidd.myapp;
import android.os.AsyncTask;
public class HeavyStuff {
public class MyTask1 extends AsyncTask<String, String, String> {
//...
//...
}
public class MyTask2 extends AsyncTask<String, String, String> {
//...
//...
}
}
The class can also be seen here in full: http://hastebin.com/yahihokupu
What am I missing that is required to make the class an "enclosing class".
-----EDIT-----
I've looked at the answer that was given as a possible duplicate to my question and it does not work. The answer given recommends using static for my inner class, but this doesn't work for me.
I have however found that I can do this:
HeavyStuff.MyTask1 myTask1 = new HeavyStuff().new MyTask1();
myTask1.execute();
It works, but what are the implications (if any) when doing it like this? Is it bad practice?
I understand that you put both MyTask1 and MyTask2 into the same class because they are similar, however in general this is not ideal.
If you plan on creating new instances of MyTask1 and also new instances of MyTask2 throughout your code base, then they should be in their own completely separate classes (i.e. MyTask1.java containing only class MyTask1).
You can still keep them "together" by putting them within the same java package, for example:
package.heavystuff
.
I have found an answer to my question. I originally posted what I believe is a solution as an edit, but to clarify, this is my working answer:
HeavyStuff.MyTask1 myTask1 = new HeavyStuff().new MyTask1();
myTask1.execute();
I need to use two classes with the same name but different namespaces (foo.request.Response and bar.request.Response) in an interface. In classes this can be achieved by using the full name with namespace :
public foo.request.Response method1() { [...]
public bar.request.Response method2() { [...]
But this does not seem to work in Interfaces.
What is the correct way of dealing with this problem ?
Edit 1
Error comes from Eclipse :
foo cannot be resolved to a type
Interface code :
public interface ITestController {
String method1(foo.request.Response response);
}
I found the issue, it was not coming from the interface it was a simple mess-up in the dependencies. Thanks for your help ;)
It works in interfaces, but care should be taken so that the implementing classes fully qualify the names in the same way.
Note that you can not choose which of the two classes when implement the interface. It's the interface that specifies which of the two classes is to be used when implementing the interface.
The code you've posted in your answer is messed up. If the two first methods belong to a class implementing ITestController then that class must also include an implementation for
public String method1(foo.request.Response response) { ... }
I just encounter a real problem about changed API. And i want to know more about this topic.
Using the following example as a demo.
There are 4 simple classes, Child class extends Parent. PubAPI is the class which provides public method for cient use. Client class invokes PubAPI's public methods.
public class Parent
{
}
public class Child extends Parent
{
}
public class PubAPI
{
public Parent getChild(){
return new Child();
}
}
public class Client
{
public static void main(String[] args)
{
System.out.println(new PubAPI().getChild());
}
}
The first 3 class is provided by an API maker, let's say the above version is version 1.
in Version 2, the PubAPI class is changed to return child type :
public class PubAPI
{
public Child getChild(){
return new Child();
}
}
the 3 API provider class is in versoin 2 now, while if we don't recompile the "Client" class and use its version 1 generated class file. IT will fail in java runtime with error can not find the version 1 method (because the return type changes).
I don't know this before, and i want to know if anyone know more about this topic , for example, if the public API add a throw, or addd a synchronize or the class become final, etc. In these situation, how will it hehave.
IN all, what is the public API/class bytecode level compabability rule for API classes used by others.
thanks.
EDIT: You asked almost the exact same question two weeks back and accepted an answer. I am wondering what prompted you to ask again, you didn't think the rules would have changed in two weeks, did you?
You are on the right track with the keyword bytecode level compatibility. It is called binary compatibility which you can look up on the net. For example, here
The rules are not always easy to understand at first but usually make sense when you get an error and think about them. Best thing is to try the individual cases you have listed and when you get an error confirm in JLS that is an incompatibility and then try and rationalize for yourself why it is so.
This question on so seems to discuss the exact same issue. The document at eclipse it sites is an easier read than JLS.