doesn't compile: sparkjava exception handling - java

I am trying to follow the sparkjava exception handling example located here, without success: http://sparkjava.com/documentation.html#exception-mapping. It appears the code they posted isn't quite right? I was able to fix one of the posted methods so that it compiles. The method on the documentation page which doesn't compile was:
get("/throwexception", (request, response) -> {
throw new NotFoundException();
});
I changed to this code and it compiles:
get(new Route("/throwexception") {
#Override
public Object handle(Request request, Response response) {
throw new IllegalArgumentException();
}
});
However, I am unable to get this method to compile. What is wrong? I am using java 8 and IntelliJ community edition 15.0.2 to compile. My java module is set to language level 8. Here is the suspect method:
exception(Exception.class, (e, request, response) -> {
//TODO: implement this after it compiles.
});
Here is the error I get from the compiler:
Error:(83, 9) java: cannot find symbol
symbol: method exception(java.lang.Class<java.lang.Exception>,(e,request[...]->{ })
location: class org.me.JournalController
To confirm that I really am using java 8, this example using a lambda expression does compile:
public class Lambdas {
public static void main(String[] args) throws Exception {
new Lambdas().start();
Thread.sleep(1000);
}
public void start(){
Interface f = () -> System.out.println("test");
}
}

The original code uses lambda expressions, you should use Java 8 to compile it.

My maven file had sparkjava dependency listed twice. I think my IDE automatically imported 1.1.1 for me at some point and I didn't realize it. I had 1.1.1 and 2.3. When I removed the outdated 1.1.1 sparkjava dependency then everything works as expected.

You can extract your throw statement into a function:
get("/throwexception", () -> BlowUp());
(snip)
public static void BlowUp()
{
throw new NotFoundException();
});

Related

Double colon operator not working with Java

just trying out things in java, found following issue.
DefaultAndStaticMethodMain.java:8: error: not a statement
implementation1::sendNotification;
^
1 error
Following is my code.
ParentInterface:
public interface ParentInterface {
default void callForCompletion() {
System.out.println("<<<< Notification sending completed. >>>>");
}
}
Child interface:
public interface ChildInterface extends ParentInterface {
public abstract void sendNotification();
static String printNotificationSentMessage() {
return "Notification is sent successfully.";
}
}
Implementation 1:
public class Implementation1 implements ChildInterface {
#Override
public void sendNotification() {
System.out.println("Implementation --- 1");
System.out.println("Sending notification via email >>>");
}
}
Implementation 2:
public class Implementation2 implements ChildInterface {
#Override
public void sendNotification() {
System.out.println("Implementation ---- 2.");
System.out.println("Sending notification via SMS >>>");
}
}
Main method:
public class DefaultAndStaticMethodMain {
public static void main(String[] args) {
Implementation1 implementation1 = new Implementation1();
implementation1::sendNotification; // Compilation error as shown above.
Implementation2 implementation2 = new Implementation2();
implementation2.sendNotification();
// Following works fine.
// Arrays.asList(implementation1, implementation2).stream().forEach(SomeInterfaceToBeRenamed::sendNotification);
}
}
I am not sure what am I doing wrong, I have JDK 13 installed in local machine and working with IntelliJ 2019.3 with JDK 11. I checked that IntelliJ supports JDK 13
Thanks.
Update
By mistake I left a semi-colon over there, removed it, please check again.
A method reference is not the same as a method call. Those are two distinct things.
A method call is a standalone expression, or, more precisely, an expression statement. That means that in your case implementation2.sendNotification() works, as you would expect.
A method reference, however,
is used to refer to the invocation of a method without actually performing the invocation
and is not a standalone expression. It can only be used where a lambda expression can also be used. A method reference as a standalone expression does not compile, just like an arithmetic expression without assignment (e.g. 3 + 17;). This is enforced by the Java Language Specification, § 14.8 and § 15.13.
More to read:
Please Explain Java 8 Method Reference to instance Method using class name
Method reference in Java 8
What do you intend for the implementation1::sendNotification; line to do? Judging by the implementation2.sendNotification(); line below it looks like you're trying to call sendNotification on implementation1, which is written like this:
implementation1.sendNotification();
The :: notation is a method reference, and (as the error message says) it an identifier, not a statement, and thus can't be a line on its own. Similarly you couldn't write implementation1; (a variable) or ChildInterface; (a class identifier) as a statement.
The .forEach(SomeInterfaceToBeRenamed::sendNotification); line compiles because you are passing the method reference to forEach(), and it in turn invokes each sendNotification() method.

How to pass the JSON object in java function using JSNI?

I am learning GWT, I am trying following example in which I have tried to pass the JSON object in java function.
public class HomeController implements EntryPoint {
public void onModuleLoad() {
createTestNativeFunction();
Presenter presenter = new PersenterImpl();
presenter.go(RootPanel.get());
}
public native void createTestNativeFunction()/*-{
parser: function() {
var that = this;
var jsonResult = JSON.parse({id:42,name:'yo'});
return this.#com.easylearntutorial.gwt.client.HomeController::onParse(Lorg/sgx/jsutil/client/JsObject;)(jsonResult);
}
void onParse(jsonResult){
System.out.println(jsonResult);
}
}
}-*/;
}
I am getting following errors:
Tracing compile failure path for type 'com.easylearntutorial.gwt.client.HomeController'
[ERROR] Errors in 'file:/C:/Users/ameen/workspace/Tutorial/src/com/easylearntutorial/gwt/client/HomeController.java'
[ERROR] Line 31: missing ; before statement
void onParse(jsonResult){
--------------------------------^
[ERROR] Hint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly
[WARN] Server class 'com.google.gwt.dev.shell.jetty.JDBCUnloader' could not be found in the web app, but was found on the system classpath
[WARN] Adding classpath entry 'file:/C:/Program%20Files/gwt-2.7.0/gwt-dev.jar' to the web app classpath for this session
For additional info see: file:/C:/Program%20Files/gwt-2.7.0/doc/helpInfo/webAppClassPath.html
You really should try to avoid JSNI. You can probably write 99% of your code not using JSNI at all. If you really need it, you should use the new JsInterop instead, documentation still in early stage but you can see this documentation here.
If you need to use JsInterop or JSNI it is usually because you need to wrap a JS lib, so first, try to find if it is already wrapped. If it is not you can always use some other wrapper library to learn how to wrap your JS lib.
OpenLayers JsInterop wrapper https://github.com/TDesjardins/gwt-ol3
OpenLayers JSNI wrapper (deprecated) https://github.com/geosdi/GWT-OpenLayers
Or explore github https://github.com/search?q=topic%3Agwt+topic%3Ajsinterop
System.out.println() is a java function, you are looking for console.log().
The body of the native is JavaScript, not Java.
You are declare you variable jsonResult into your parser: function(), jsonResult only exist into that function. Thats why the system say you that
missing ; before statement
Because you never declare the varieble into createTestNativeFunction().
Plus sjakubowski is right System.out.println() is a java function, you need to use console.log() on JavaScript.
Try this:
public native void createTestNativeFunction(){
var jsonResult = {};
parser: function() {
var that = this;
jsonResult = JSON.parse({id:42,name:'yo'});
return this.#com.easylearntutorial.gwt.client.HomeController::onParse(Lorg/sgx/jsutil/client/JsObject;)(jsonResult);
}
void onParse(jsonResult){
console.log(jsonResult);
}
}
I did the following to solve my errors.
public class HomeController implements EntryPoint {
public void onModuleLoad() {
createTestNativeFunction();
Presenter presenter = new PersenterImpl();
presenter.go(RootPanel.get());
}
// var jsonResult = JSON.parse({id:42,name:'yo'});
public native void createTestNativeFunction()/*-{
var that = this;
$wnd.testFunction = function(jsonResult) {
that.#com.easylearntutorial.gwt.client.HomeController::onParse(Lorg/sgx/jsutil/client/JsObject;)(jsonResult);
};
}-*/;
public void onParse(JsObject jsonResult){
int i =42;
}
}

SonarLint - RedundantThrowsDeclarationCheck - false positive?

In the following code I get a warning from the squid:RedundantThrowsDeclarationCheck rule on the Foo1Exception (behind the throws keyword): Remove the redundant '!unknownSymbol!' thrown exception declaration(s).
Foo.java:
public class Foo {
public static boolean bar(final String test) throws Foo1Exception, Foo2Exception {
if (test.startsWith("a")) {
throw new Foo1Exception();
} else if (test.startsWith("b")) {
throw new Foo2Exception();
} else if (test.startsWith("c")) {
return true;
}
return false;
}
}
Both exceptions are decrlared in seperate files:
Foo1Exception.java:
class Foo1Exception extends Exception {}
Foo2Exception.java:
class Foo2Exception extends Exception {}
I think this is a false positive, isn't it?
Also interesting: I don't get this message directly in SonarQube (web interface) only in the SonarLint plugin in IntelliJ IDEA.
Any Ideas?
I'm using: IntelliJ IDEA 2016.2.2; SonarLint 2.3 (with working server binding); SonarQube 5.6; SonarQube Java Plugin 4.0; Java 8
This seems to be fixed in SonarLint 2.3.1.

RoboSpice throwing okhttp exceptions

I use RoboSpice-Retrofit for calling my server REST api which has been working without problems until a few days ago when every single call now throws an exception, Example:
D/Retrofit: java.lang.NoSuchMethodError: No direct method <init>(Lcom/squareup/okhttp/OkHttpClient;Lcom/squareup/okhttp/Request;ZZZLcom/squareup/okhttp/Connection;Lcom/squareup/okhttp/internal/http/RouteSelector;Lcom/squareup/okhttp/internal/http/RetryableSink;Lcom/squareup/okhttp/Response;)V in class Lcom/squareup/okhttp/internal/http/HttpEngine; or its super classes (declaration of 'com.squareup.okhttp.internal.http.HttpEngine' appears in /data/app/com.company.app.customerapp-1/base.apk)
at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.newHttpEngine(HttpURLConnectionImpl.java:362)
at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.initHttpEngine(HttpURLConnectionImpl.java:312)
at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:377)
at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497)
at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:73)
at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:38)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:321)
at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
at java.lang.reflect.Proxy.invoke(Proxy.java:393)
at $Proxy0.getTest(Unknown Source)
at com.adoperator.tidyapp.TestActivity$TestRequest.loadDataFromNetwork(TestActivity.java:67)
at com.adoperator.tidyapp.TestActivity$TestRequest.loadDataFromNetwork(TestActivity.java:54)
at com.octo.android.robospice.request.CachedSpiceRequest.loadDataFromNetwork(CachedSpiceRequest.java:48)
at com.octo.android.robospice.request.DefaultRequestRunner.processRequest(DefaultRequestRunner.java:150)
at com.octo.android.robospice.request.DefaultRequestRunner$1.run(DefaultRequestRunner.java:217)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
D/Retrofit: ---- END ERROR
dependencies:
compile 'com.octo.android.robospice:robospice:1.4.14'
compile 'com.octo.android.robospice:robospice-cache:1.4.14'
compile 'com.octo.android.robospice:robospice-retrofit:1.4.14'
I suspect based on the exception that there is something wrong with the compiler, but I just tested on another computer with a fresh install of Java and Android Studio on the same project but same problems still...
This error is driving me crazy...
Anyone knows anything that could be of help? Any help is highly appreciated.
EDIT
MainActivity.java:
SpiceManager spiceManager = new SpiceManager(TestAPIService.class);
protected void onStart() {
super.onStart();
spiceManager.start(this);
spiceManager.execute(new TestRequest(), new RequestListener<ResponseData>() {
...
});
}
TestAPIService.java:
public class TestAPIService extends RetrofitGsonSpiceService {
#Override
public void onCreate() {
super.onCreate();
addRetrofitInterface(TestAPI.class);
}
#Override
protected String getServerUrl() {
return "http://192.168.0.2";
}
}
TestAPI.java:
public interface TestAPI {
#GET("/test")
ResponseData getTest();
}
TestRequest.java:
public class TestRequest extends RetrofitSpiceRequest<ResponseData, TestAPI> {
public TestRequest() {
super(ResponseData.class, TestAPI.class);
}
#Override
public ResponseData loadDataFromNetwork() throws Exception {
ResponseData response;
try {
response = getService().getTest();
}
catch (Exception e) {
e.printStackTrace();
throw e;
}
return response;
}
}
The NoSuchMethodError is happening because HttpURLConnectionImpl is trying to invoke a constructor on HttpEngine that is not defined. Now your project depends on:
com.octo.android.robospice:robospice-retrofit:1.4.14
Which depends on:
com.squareup.retrofit:retrofit:1.6.1
Which depends on both:
com.squareup.okhttp:okhttp:2.0.0
and
com.squareup.okhttp:okhttp-urlconnection:2.0.0
As of version 2.0.0, HttpURLConnectionImpl is in the okhttp-urlconnection module and HttpEngine is in the okhttp module.
The retrofit.client.UrlConnectionClient portion of your stack trace correctly matches retrofit:1.6.1, but the com.squareup.okhttp.internal.huc.HttpURLConnectionImpl portion doesn't match okhttp-urlconnection:2.0.0; it matches okhttp-urlconnection:2.4.0. The constructor that the NoSuchMethodError is complaining about is indeed defined in okhttp:2.4.0, so that means there is a different HttpEngine on your classpath, most likely from a different version of okhttp that is getting pulled in by a transitive dependency. You should be able to fix the problem by specifying the following dependencies:
compile('com.squareup.okhttp:okhttp:2.0.0') {
force = true
}
compile('com.squareup.okhttp:okhttp-urlconnection:2.0.0') {
force = true
}
If that doesn't work for whatever reason, the solution to your problem will still be to get your versions of okhttp and okhttp-urlconnection synced up and at a version that is compatible with your version of retrofit. Declare dependencies similar to above, find the jars that contain HttpURLConnectionImpl and HttpEngine, figure out how they're getting pulled in to your build, and use exclusions to get rid of problematic transitive dependencies.

Lambda/default methods/type erasure quirk/bug using ECJ?

Came accross this today and spent ages trying to reproduce/figure out what was happening. Can somebody explain why this happens or is this a bug with type erasure/default methods/lambda's/polymorphism? Uncommenting the default method makes it run fine, but I would have expected this to work as is
Output:
Works fine with an object
Calling consume
Hello
Calling accept with context
Hello
Calling accept via consumer...
Exception in thread "main" java.lang.AbstractMethodError: Method test/LambdaTest$$Lambda$1.accept(Ljava/lang/Object;)V is abstract
at test.LambdaTest$$Lambda$1/834600351.accept(Unknown Source)
at test.LambdaTest.main(LambdaTest.java:24)
Code
package test;
import java.util.function.Consumer;
public class LambdaTest {
public static void main(String[] args) {
Consumer<Context> contextIgnoringObject = new ContextUnawareObject();
contextIgnoringObject.accept(new Context());
ContextIgnorer contextIgnoringLambda = () -> {
System.err.println("Hello");
};
System.err.println("Calling consume");
contextIgnoringLambda.consume();
System.err.println("Calling accept with context");
contextIgnoringLambda.accept(new Context());
Consumer<Context> consumer = contextIgnoringLambda;
System.err.println("Calling accept via consumer...");
consumer.accept(new Context());
}
#FunctionalInterface
public interface ContextIgnorer extends Consumer<Context> {
// default void accept(Object object) {
// System.err.println("Manual bridge method");
// accept((Context)object);
// }
#Override
default void accept(Context context) {
consume();
}
void consume();
}
public static class ContextUnawareObject implements ContextIgnorer {
#Override
public void consume() {
System.err.println("Works fine with an object");
}
}
public static class Context {
}
}
The problem appears with older ECJ compiler (3.10.0):
$ java -jar org.eclipse.jdt.core-3.10.0.v20140604-1726.jar -source 1.8 LambdaTest.java
$ java LambdaTest
Works fine with an object
Calling consume
Hello
Calling accept with context
Hello
Calling accept via consumer...
Exception in thread "main" java.lang.AbstractMethodError: Method LambdaTest$$Lambda$1.accept(Ljava/lang/Object;)V is abstract
at LambdaTest$$Lambda$1/424058530.accept(Unknown Source)
at LambdaTest.main(LambdaTest.java:24)
Using org.eclipse.jdt.core_3.10.0.v20140902-0626.jar or newer solves the problem. The Oracle javac compiler has no such problem. Thus the solution would be to update your ECJ compiler or move to the javac.

Categories