I have to develop an "generic" wigdet for a GWT/GXT project and to do so I need to create an instance of an object which type is unknown. I found an approach that works perfectly in dev mode but as soon as I try to compile my project and deploy it I get an Only class literals may be used as arguments to GWT.create() error.
Here is a sample of what I do:
public class GenericEditableGrid<M> extends Grid<M>{
private final ToolBar toolBar = new ToolBar();
private final TextButton newItemButton = new TextButton();
protected GridInlineEditing<M> editing;
private final Class<M> clazzM;
public GenericEditableGrid(Class<M> parametrizedClass, String gridTitle, ListStore<M> listStore, ColumnModel<M> cm) {
super(listStore, cm);
clazzM = parametrizedClass;
// ... then I create my widget
bind();
}
private void bind(){
newItemButton.addSelectHandler(new SelectEvent.SelectHandler() {
#Override
public void onSelect(SelectEvent selectEvent) {
editing.cancelEditing();
// it is the folliwing line which is the problem obviously
M element = GWT.create(clazzM);
getStore().add(0, element);
int index = 0;
editing.startEditing(new Grid.GridCell(getStore().indexOf(element), index));
}
});
}
}
And this is how I use it in my subclasses:
super(InternationalString.class, gridTitle, new ListStore<InternationalString>(isprops.key()), buildColumnModel());
Basically, I would like to know what the problem is exactly with this approach and eventually how I should do to make it well.
Please note that my concern is not just to make it work, but more to do it the right way. As I could just avoid the problem using an abstract method which would handle the GWT.create() method in the daughter classes. But this is not the design I want, it just doesn't look right.
What I don't get also is what's the difference between doing this:
MyClass e = GWT.create(MyClass.class);
and:
Class<MyClass> clazz=MyClass.class;
MyClass e = GWT.create(clazz);
Because as far as I am concerned I think this is basically what I am doing and it looks like the same thing. Isn't it?
There's a well-worded explanation in this forum:
As the error message indicates, only class literals may be passed to the GWT.create method. The reason for this is that all GWT.create calls are basically turned into constructors at compile time, using the deferred binding rules for your module. As a result, all classes must be decided at compile time - your code requires that the at runtime the class is decided. This is too late, and so cannot be compiled.
GWT is not proper java, and so cannot be always treated as java. This is one such example of things that cannot be done in gwt. ...
What is it you are trying to do? Either you are making it far more complicated than it needs to be, or you need to write a generator to do it instead of taking this approach.
Related
I am using this library which is a CalendarView. https://github.com/kizitonwose/CalendarView
In the sample code there is the following code which attaches a Scroll Listener to the CalendarView
calendarView.monthScrollListener = { // etc}
I am unsure how to translate this to Java, I try the following but the "MonthScrollListener" class is nowhere to be found, its like it want some other type but I cannot find the type. Everything else has worked so far when translating the Kotlin to Java but I cannot see how this might work
mBinding.calendarView.setMonthScrollListener(new MonthScrollListener(){ // etc});
What should I pass into the setMonthScrollListener() method?
Edit: when I "ctrl click" on the setMonthScrollListener() it takes me into the CalendarView class and there is the following line:
public final var monthScrollListener: com.kizitonwose.calendarview.ui.MonthScrollListener? /* = ((com.kizitonwose.calendarview.model.CalendarMonth) -> kotlin.Unit)? */ /* compiled code */
So I try explicitly referencing the MonthScrollListener but everything is resolved up to the MonthScrollListener, which isnt available...
typealias is not visible in Java, but given the example you're talking about is:
typealias MonthScrollListener = (CalendarMonth) -> Unit
Then in Java world it should be similar to single method interface like (more about it below):
import kotlin.Unit;
interface MonthScrollListener {
Unit whatever(CalendarMonth cm);
}
It could be void because this is what Unit means in Kotlin but you know - life.
So passing Lambda in that method which expects listener should look like:
whatever.setMonthScrollListener((CalendarMonth cm) -> {
// w00t
return kotlin.Unit.INSTANCE;
});
I've basically ended up writing the same approach as suggested by #MishaAkopov
Edit (after reading about it):
But what type is it actually? It appears that Kotlin standard library has a bunch of interfaces like Function0<R> and Function2<P1,P2,R> that have one method invoke. So if you'd need to use above Kotlin code in previous Java versions it would instead look like:
Function1<CalendarMonth, Unit> listener = new Function1<CalendarMonth, Unit>() {
#Override
public Unit invoke(CalendarMonth cm) {
// Do something with calendar month
return kotlin.Unit.INSTANCE;
}
}
whatever.setMonthScrollListener(listener);
I had difficulties finding a relevant title since it is not a simple issue. I will try to explain. I have a class responsible of error reporting whose methods basically wrap multiple ways of reporting an error.
For example, I have a method failTest:
public static void failTest(Logger log, Exception e, String message, boolean reportToES, String esTestPath, String esTestSet, String esTestInstance)
{
log.error(e, message);
someExternalErrorReportingService(reportToES, esTestPath,esTestSet,esTestInstance);
Assert.fail(e,message);
}
And I call this error reporting method in many, many places and it doesn't seem a good practice (too many parameters, hard to follow their order etc.) to just call it with the es* parameters each and every time because they don't change very often so they could be set up once and then reused.
And I came up with this version
public static void failTest(Logger log, Exception e, String message)
{//same body
}
And then added method to set up es* parameters
setES(boolean reportToES, String esTestPath, String esTestSet, String esTestInstance)
{
this.reportToES = reportToES;
this.esTestPath = esTestPath;
this.esTestSet = esTestSet;
this.esTestInstance=esTestInstance;
}
and of course added these instance variables above.
And only now I can enunciate the issue:
now if I want to use this error reporting class I need to first instantiate it and set the es* fields. The issue is that I often need to use the error reporting in a utility class that could be static but now, with my change above, I have to instantiate it and set up the error reporting class in order to have the es* fields set before I call failTest().
To conclude, I don't like this solution either because I can't use static utility classes anymore and moreover some utility classes are already used in a static way so cannot be refactored to non-static and will end up being used sometimes static, sometimes instantiated.
So the question is, do you see a better solution in order to simplify the calling of failTest() in utility classes?
To give you an example, we have a client that
sets up the error reporting class and sets up its es* fields
This client calls utility method Utility.doSomething
public static doSomething(reportToES, esTestPath, esTestSet, esTestInstance)
{
try{
methodThatThrowsFatalException()
}
catch(Exception e){
failTest(log, e, "Some smart message",reportToES, esTestPath, esTestSet, esTestInstance);
}
}
Now, in order to reduce the number of parameters we can just add setErrorReportingInstance to the Utility class,
then in client instantiate the Utility, then utilityInstance. setErrorReportingInstance(configuredErrorReportingInstance). And doSomething becomes:
public static doSomethingRefactored()
{
try{
methodThatThrowsFatalException()
}
catch(Exception e){
errorReportingInstance.failTest(log, e, "Some smart message");
}
}
What is not ok, from my point of view, is that:
1. I have complicated the usage of Utility. Now I have to make sure it is instantiated before I use it. It's inconvenient when having a lot of Utility like classes.
2. I cannot make static methods in Utility if I have to do error reporting in their implementation.
3. The methods that are already used as static will remain with the es* parameters in their signature (due to backward compatibility). So I will have in the same class methods like doSomething and also methods like doSomethingRefactored.
4. I have created a dependency between utility classes and error reporting so I have an issue when I need to test the utility methods
The question is, how can I keep the simple design of utility classes as simple collection of static utility methods but in the same time use the error reporting class but without passing too many parameters since it is bad practice?
More details:
Actually the client is many TestNG test cases:
So first I had :
class TestClass1
{
static final boolean REPORT_TO_ES="true",
static final String ES_TEST_PATH="somePath", //and so on for the others
#Test
{
Utility1.doSomething(REPORT_TO_ES,ES_TEST_PATH,ES_TEST_SET,...
Utility2.doSomethingElse(REPORT_TO_ES,ES_TEST_PATH,ES_TEST_SET,...
Utility3.doSomethingMoreUseful(REPORT_TO_ES,ES_TEST_PATH,ES_TEST_SET,...
Utility4.doSomethingSomething(REPORT_TO_ES,ES_TEST_PATH,ES_TEST_SET,...
}
And then I would try to get rid of calling the doSomethings with the ES* values
by setting them once on the ErrorReporter instance (so I would also make ErrorReporter non-static).
class TestClass1
{
private ErrorReporter errorReporter = new ErrorReporter();
errorReporter.setReportToEs(true);
errorReporter.setEsTestPath("somePath");//and so on
Utility1 utility1Instance = new Utility1();
utility1Instance.setErrorReporter(errorReporter);
Utility2 utility1Instance = new Utility2();
utility2Instance.setErrorReporter(errorReporter);
#Test
{
utility1Instance.doSomething();
utility2Instance.doSomethingElse();
...
The title to your question should be "Static Mess".
Take a look at how real loggers work and you may get some ideas. Log4J and Slf4j are well respected ones. You need to control all of your static variables. You could create a Logger class that encapsulates the ES data and does the real work of logging:
// Does the real work of logging.
class Logger {
public Logger(all of your es data)
public fail(String msg) // Logs msg
}
Then you need a static collection of these Loggers referenced by name (I assume you have more than one set of es data). This gives you a central place to go get the loggers. Works if you're in a static method or somewhere else. The static collection goes inside the LogFactory object
class LogFactory {
private static Map<String, Logger> loggers ...
public static Logger get(String name) ...
}
Here is your static method using the new logger:
public static doSomething() {
try {
methodThatThrowsFatalException()
}
catch(Exception e){
LogFactory.get("Util").failTest(e, "Some smart message");
}
}
I would add a clear or reset method to LogFactory so that you have a chance of writing JUnit tests for your code. For the same reason I would write a NullLogger (in which case you might want to pull out an interface that the NullLogger and the EsLogger can both implement.
You need to decide how to add Loggers to LogFactory. I suggest doing it in your main class. Resist the temptation to do it in a static initializer.
LogFactory could also be written so it holds a collection and not a static collection. You then just keep a static reference (a Singleton) to it. Just keep in mind that you'll want a way to clear the Singleton to make unit testing possible.
Good luck.
am working on a Jenkins plugin and evaluating unit testing software at the same time, and came upon a learning opportunity. The software wrote a test case for this method-
public boolean isApplicable(Class<? extends AbstractProject> aClass) {
// indicates that this builder can be used with all
// kinds of project types
return true;
}
Seems pretty straightforward. The test case doesn't compile though, and I have not been able to figure out how to fix it from my limited knowledge of using wildcards. My current attempt-
AbstractProject ap = new FreeStyleProject(null, null);;
Assert.assertTrue(testedObject.isApplicable(ap));
(FreeStyleProject extends AbstractProject)
This gives the error message
The method isApplicable(Class) in the type FitnesseBuilder.DescriptorImpl is not applicable for the arguments (AbstractProject)
I have tried a variety of types to pass to that argument, but cannot seem to get it to accept anything. Anyone feel like giving me a quick lesson?
You need to pass the Class<T> object, not an instance of that class:
// AbstractProject ap = new FreeStyleProject(null, null);
Assert.assertTrue(testedObject.isApplicable(FreeStyleProject.class));
Of course, FreeStyleProject class needs to extend AbstractProject (since the first line of your current code compiles, it does that already).
Try Assert.assertTrue(testedObject.isApplicable(FreeStyleProject.class)); as it takes an instance of Class rather than AbstractProject
I have started reading the Spring in Action book.
I have no knowledge of JUnit which I think my doubt is about.
There is a code fragment where the author refers to and says that it is difficult to test:
package com.springinaction.knights;
public classDamselRescuingKnight implements Knight {
private RescueDamselQuest quest;
public DamselRescuingKnight() {
quest = new RescueDamselQuest();
}
public voidembarkOnQuest() throwsQuestException {
quest.embark();
}
}
The author says that:
It’d be terribly difficult to write a unit test for DamselRescuingKnight. In such a test, you’d like to be able to assert that the quest’s embark() method is called when the knight’s embarkOnQuest() is called. But there’s no clear way to accomplish that here. Unfortunately, DamselRescuingKnight will remain untested.
What does the author mean by this?
Why is the code difficult to test here?
My initial thought is that it is difficult to test because the "RescureDamselQuest" object is initialized in the constructor. This makes it difficult to for example insert a mock object. A mock object would help you test that the embark() method is called on the "RescueDamselQuest" object.
A better way to solve this can be to either include a parameter in the constructor (usually I prefer this method):
public DamselRescuingKnight(RescueDamselQuest quest){
this.quest = quest;
}
Or add a setter:
public void setDamselRescuingKnight(RescueDamselQuest quest){
this.quest = quest;
}
A common example I give is consider that you want to open a file, parse it, and get a data class out. Most will do something like:
Data openAndParse(String filename) {
...openFile
...parse
}
By doing it this way, the file open methodology and parse is highly coupled and difficult to test. If you have a problem in open and parse is it with the parse or the open?
By writing JUnit test, you are forced, for simplicity sake, to do something like...
BufferedReader openFile(String filename) {
...open file and return reader
}
Data parse(BufferedReader input) {
...parse and return data
}
JUnit leads us to a more cohesive solution. We write JUnit test simply by creating a string, constructing a StringReader, and then a BufferedReader. Well guess what? Very similarly we can now use parse to accept input from a variety of sources not just the file.
It's difficult to test because the quest implementation cannot be swapped out. Without byte code modification there's no trivial way to see if embark is called.
If you could set the quest implementation in a constructor or setter you could pass in an implementation that can spy on the call to embark.
One need to increase accessibility of fields and method of class to test. For example if one is testing a method which is package-private (default) then test cases which are generally in different package will not able to test this method. Therefore it is advised to to change in accessibility of fields to test the method. DamselRescuingKnight class can be tested which is not using DI by modifying the accessibility of RescueDamselQuest field from private to default. Then writing test case using mockito. Here is code for test case
#Test
public void knightShouldEmbarkOnQuest() throws QuestException {
DamselRescuingKnight knight = new DamselRescuingKnight();
RescueDamselQuest quest = mock(RescueDamselQuest.class);
knight.quest = quest;
knight.embarkOnQuest();
verify(quest, times(1)).embark();
}
And line which was changed in DamselRescuingKnight class to remove private accessibility
RescueDamselQuest quest;
I'm fairly new to Java. I'm coming from PHP and I used to create registry classes in php using the magic __get and __set methods. So that other parts of the system can easily do:
registry.foo = new Foo();
I should mention I'm trying to create game engine. Here is my registry in Java atm:
class Registry {
private static Map<String, Object> box = new HashMap<String, Object>();
public static Object get(String key) {
if (Registry.box.get(key) != null) {
return Registry.box.get(key);
}else {
return null;
}
}
public static void set(String key, Object o) {
Registry.box.put(key, o);
}
}
Then for the other parts of the system to access the registry, I currently need this whole thing:
((Object) Registry.get("Object")).doSomething();
Which is really a lot of code. In php this would be accomplished by simply:
Registry.foo.doSomething();
Any way to make this a bit more simpler? I guess I could make public fields, but then the regsitry class would need to implicitly create these fields as the possibility of new objects may need to be added which are unknown to the registry class itself, which is.. annoying :P
Thanks in advance!
This is a two pronged problem:
Java is a statically type language, and does not offer in-language flexibility for defining objects at runtime (you can use a library to synthesize classes at runtime, but, see #2)
A global registry for objects defeats a lot of safeties in a type-safe language. If your entire application centers around getting and putting objects into a global Map, there likely safer and less-coupled designs.
How can this be solved?
Redesign your application structure to not need a global map.
Use a dynamic language subset for Java (such as Groovy).
Use Scala 2.10 (JVM compatible) which features a Dynamic type which does exactly what you want.
First of all this method is too verbose:
public static Object get(String key) {
if (Registry.box.get(key) != null) {
return Registry.box.get(key);
}else {
return null;
}
}
It could be just:
public static Object get(String key) {
return Registry.box.get(key);
}
But second, this is definitely a bad design. Global repository - doesn't sound reasonable. A storage of objects of all types by string key - it's terrible.
Any way to make this a bit more simpler?
Not in any practical way. Java is a statically typed language, and the structure of objects has to be known up front. The very idea of an equivalent of PHP's __get and __set is antithetical to the language.
For what it's worth, your "registry" looks like bad design anyway. (Admittedly making some pretty wild assumptions from the little code you've shown.) You shouldn't need a global repository of what appear to be unrelated objects. You should consider some sort of dependency injection instead.
Based on your comment, instead of structuring your code like this:
class World implements GameSystem {
public void update() {
Registry.get("game").doSomething();
}
}
you should do:
class World implements GameSystem {
Game game;
public World(Game game) { // and other dependencies
this.game = game;
}
public void update() {
this.game.doSomething();
}
}
The idea is that components of your program don't really have any business knowing how to find the other components. It also makes dependencies between the components explicit, and helps you avoid circular dependencies.