com.android.volley.NoConnectionError: java.net.ProtocolException: Unknown method 'PATCH'; must be one of [OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE]
StringRequest putRequest = new StringRequest(Request.Method.PATCH, url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response)
{
Log.d("Response", response);
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
Log.d("Error.Response", error.toString());
}
}
) {
#Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<String, String> ();
params.put("name", "My Name");
params.put("age", "11");
return params;
}
};
Are you sure you are using correct version of Volley Library? I just tried your code in Lollipop and it is working OK.
If you are using Volley library as external project, check the Method interface of Request class in com.android.volley package. It should have a PATCH variable in it.
public interface Method {
int DEPRECATED_GET_OR_POST = -1;
int GET = 0;
int POST = 1;
int PUT = 2;
int DELETE = 3;
int HEAD = 4;
int OPTIONS = 5;
int TRACE = 6;
int PATCH = 7;
}
If not, use the latest version of Volley library.
UPDATE:
You are correct, it is showing this error in Kitkat, but not in Lollipop. I guess the main problem is that HTTPUrlConnection of Java does not support PATCH.
(I guess it works in Lollipop because it is using Java 7 and HTTPUrlConnection of Java 7 supports PATCH method?)
Anyhow, You can use the OkHttp Library to correct this problem. The okhttp-urlconnection module implements the java.net.HttpURLConnection
Add the following jar to your libs folder:
okhttp-2.2.0.jar
okhttp-urlconnection-2.2.0.jar
okio-1.2.0.jar
Create a OkHttpStack class:
package com.example.temp;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import com.android.volley.toolbox.HurlStack;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.OkUrlFactory;
public class OkHttpStack extends HurlStack {
private final OkUrlFactory mFactory;
public OkHttpStack() {
this(new OkHttpClient());
}
public OkHttpStack(OkHttpClient client) {
if (client == null) {
throw new NullPointerException("Client must not be null.");
}
mFactory = new OkUrlFactory(client);
}
#Override protected HttpURLConnection createConnection(URL url) throws IOException {
return mFactory.open(url);
}
}
Use the following constructor to create a Volley RequestQueue:
Volley.newRequestQueue(getApplicationContext(),new OkHttpStack()).add(putRequest);
It is working for me on Kitkat now.
While sending request use POST.
In headers just override http method to PATCH.
For me now its working in volley even in kitkat version.
header.put("X-HTTP-Method-Override", "PATCH");
Related
I have build a hybrid-app using flutter's web_view_plugin(webview).
One of our paying methods require to open a 3rd party app(in this case kakaotalk). But the flutter webview plugin does not provide this function and returned net::ERR_UNKNOWN_URL_SCHEME. I did some research and I understand that the problem lies in the url. If the url does not start with http or https, it will cause this error.
So, to solve this problem I had to change native java code. Now I have no experience at all with java and android, so fixing the native code was very difficult. I understand that I have to modify shouldOverrideUrlLoading part, in order to allow the url that starts with intent:// and also I have to put in some validation to check if the app is installed or not.(If not installed the user should be redirected to playstore)
The code which I added is in shouldOverrideUrlLoading.
I also did three imports. The rest is code, generated by flutter
package com.flutter_webview_plugin;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.os.Build;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Intent; //added import
import android.net.Uri; //added import
import android.content.ActivityNotFoundException; //added import
/**
* Created by lejard_h on 20/12/2017.
*/
public class BrowserClient extends WebViewClient {
private Pattern invalidUrlPattern = null;
public BrowserClient() {
this(null);
}
public BrowserClient(String invalidUrlRegex) {
super();
if (invalidUrlRegex != null) {
invalidUrlPattern = Pattern.compile(invalidUrlRegex);
}
}
public void updateInvalidUrlRegex(String invalidUrlRegex) {
if (invalidUrlRegex != null) {
invalidUrlPattern = Pattern.compile(invalidUrlRegex);
} else {
invalidUrlPattern = null;
}
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
Map<String, Object> data = new HashMap<>();
data.put("url", url);
data.put("type", "startLoad");
FlutterWebviewPlugin.channel.invokeMethod("onState", data);
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Map<String, Object> data = new HashMap<>();
data.put("url", url);
FlutterWebviewPlugin.channel.invokeMethod("onUrlChanged", data);
data.put("type", "finishLoad");
FlutterWebviewPlugin.channel.invokeMethod("onState", data);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
// returning true causes the current WebView to abort loading the URL,
// while returning false causes the WebView to continue loading the URL as usual.
String url = request.getUrl().toString();
boolean isInvalid = checkInvalidUrl(url);
Map<String, Object> data = new HashMap<>();
data.put("url", url);
data.put("type", isInvalid ? "abortLoad" : "shouldStart");
FlutterWebviewPlugin.channel.invokeMethod("onState", data);
return isInvalid;
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// returning true causes the current WebView to abort loading the URL,
// while returning false causes the WebView to continue loading the URL as usual.
if (url.startsWith(INTENT_PROTOCOL_START)) {
final int customUrlStartIndex = INTENT_PROTOCOL_START.length();
final int customUrlEndIndex = url.indexOf(INTENT_PROTOCOL_INTENT);
if (customUrlEndIndex < 0) {
return false;
} else {
final String customUrl = url.substring(customUrlStartIndex, customUrlEndIndex);
try {
view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(customUrl)));
} catch (ActivityNotFoundException e) {
final int packageStartIndex = customUrlEndIndex + INTENT_PROTOCOL_INTENT.length();
final int packageEndIndex = url.indexOf(INTENT_PROTOCOL_END);
final String packageName = url.substring(packageStartIndex, packageEndIndex < 0 ? url.length() : packageEndIndex);
view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(GOOGLE_PLAY_STORE_PREFIX + packageName)));
}
return true;
}
} else {
return false;
}
// boolean isInvalid = checkInvalidUrl(url);
// Map<String, Object> data = new HashMap<>();
// data.put("url", url);
// data.put("type", isInvalid ? "abortLoad" : "shouldStart");
// FlutterWebviewPlugin.channel.invokeMethod("onState", data);
// return isInvalid;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
super.onReceivedHttpError(view, request, errorResponse);
Map<String, Object> data = new HashMap<>();
data.put("url", request.getUrl().toString());
data.put("code", Integer.toString(errorResponse.getStatusCode()));
FlutterWebviewPlugin.channel.invokeMethod("onHttpError", data);
}
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
Map<String, Object> data = new HashMap<>();
data.put("url", failingUrl);
data.put("code", errorCode);
FlutterWebviewPlugin.channel.invokeMethod("onHttpError", data);
}
private boolean checkInvalidUrl(String url) {
if (invalidUrlPattern == null) {
return false;
} else {
Matcher matcher = invalidUrlPattern.matcher(url);
return matcher.lookingAt();
}
}
}
The code compiles, but it still returns the same error net::ERR_UNKNOWN_URL_SCHEME when I try to pay with the "3rd party app(kakaotalk)"
I encountered a similar error on Android before when Firebase Dynamic Links are being forced to be loaded in a WebView. In my case, FDL is expected to be handled by Google Play Services in Android. But since the WebView doesn't know what to do with the link it's forced to display, the WebView returns "net::ERR_UNKNOWN_URL_SCHEME" error. I'm unsure if this is the same case as yours since I'm unable to verify the link that you're trying to load apart from "intent://kakaopay..."
You can try opening the link externally by using url_launcher. Use RegEx to filter intent URLs and check if the URL can be launched and be handled externally (outside the app).
var yourURL = "URL goes here";
// Check if URL contains "intent"
yourURL.contains(RegExp('^intent://.*\$')){
// Check if the URL can be launched
if (await canLaunch(yourURL)) {
await launch(yourURL);
} else {
print('Could not launch $yourURL');
}
}
Also, the plugin (web_view_plugin) that you're using seems to be outdated, and I can't find it here https://pub.dev/packages?q=web_view_plugin. Flutter has its official WebView plugin (webview_flutter) that has been released and I suggest checking it out if it fits your use case.
Listen, In some cases using #omatt's answer might not work, especially for webview_flutter. I struggled to find a solution so I did this:
_launchURL(url) async {
var link = "https://hiddenwords.page.link/deposit";
if (await canLaunch(link)) {
await launch(link,
forceWebView: false, enableJavaScript: true, forceSafariVC:
false);
} else {
throw 'Could not launch $link';
}
}
I manually put the url/link I wanted it to open in the _launch function... Dont mind the url in the _launch parenthesis.
I also added this to the Webview widget:
navigationDelegate: (NavigationRequest request) {
if (request.url.contains(RegExp('^intent://.*\$'))) {
_launchURL(request.url);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
Hope this works for you. It works for me...
1.Use your APP open other app in flutter with parameter(in your dynamic link);
2.use: url_launcher: ^6.1.6;
First, their app must support dynamic link;
Second, they provide you with dynamic links for their deals;
In this way, we can click the dynamic link in your APP and jump to the specified page of their APP.
Code:
final Uri toLaunch = Uri(scheme: 'https', host: 'link.fitstop.com', path: 'link/qbvQ/');
//https://link.fitstop.com/link/qbvQ is dynamic link
Future<void>? _launched;
ElevatedButton(
onPressed: () => setState(() {
_launched = _launchInBrowser(toLaunch);
}),
child: Text(
'url_launcher',
),
)
Future<void> _launchInBrowser(Uri url) async {
if (!await launchUrl(
url,
mode: LaunchMode.externalApplication,
)) {
throw 'Could not launch $url';
}
}
I'm using parseq framework for asynchronous computation.
Consider the following code. It first queries the content of google.com and then map the content to it's length. Finally, the length is printed.
The problem is that only the first task is ran. Why?
public class Main {
public static void main(String[] args) throws Exception {
OkHttpClient okHttpClient = new OkHttpClient();
final int numCores = Runtime.getRuntime().availableProcessors();
final ExecutorService taskScheduler = Executors.newFixedThreadPool(numCores + 1);
final ScheduledExecutorService timerScheduler = Executors.newScheduledThreadPool(numCores + 1);
final Engine engine = new EngineBuilder()
.setTaskExecutor(taskScheduler)
.setTimerScheduler(timerScheduler)
.build();
Task<Integer> task = Task.async(() -> {
SettablePromise<String> promise = Promises.settable();
Request request = new Request.Builder()
.url("http://google.com")
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
System.out.println("error");
}
#Override
public void onResponse(Call call, Response response) throws IOException {
promise.done(response.body().string());
}
});
return promise;
}).map("map content to length", content -> content.length())
.andThen(System.out::println);
engine.blockingRun(task);
engine.blockingRun(task);
}
}
I was able to solve your problem with the use of HttpClient instead of OkHttp .
Below are the overall maven dependencies that i used for this code:
<dependency>
<groupId>com.linkedin.parseq</groupId>
<artifactId>parseq</artifactId>
<version>3.0.11</version>
</dependency>
<dependency>
<groupId>com.linkedin.parseq</groupId>
<artifactId>parseq-http-client</artifactId>
<version>3.0.11</version>
</dependency>
import com.linkedin.parseq.Engine;
import com.linkedin.parseq.EngineBuilder;
import com.linkedin.parseq.Task;
import com.linkedin.parseq.httpclient.HttpClient;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
public class Main {
private static Task<Integer> fetchBody(String url) {
Task<Integer> map = HttpClient.get(url).task().map("map content to length", content -> content.getResponseBody().length());
return map;
}
public static void main(String[] args) {
final int numCores = Runtime.getRuntime().availableProcessors();
final ExecutorService taskScheduler = Executors.newFixedThreadPool(numCores + 1);
final ScheduledExecutorService timerScheduler = Executors.newScheduledThreadPool(numCores + 1);
final Engine engine = new EngineBuilder()
.setTaskExecutor(taskScheduler)
.setTimerScheduler(timerScheduler)
.build();
final Task<Integer> stackOverFlow = fetchBody("http://www.stackoverflow.com");
final Task<Integer> google = fetchBody("http://www.google.com");
final Task<Integer> ethereum = fetchBody("http://ethereum.stackexchange.com");
final Task<String> plan = Task.par(stackOverFlow, google, ethereum)
.map((s, g, e) -> "StackOverFlow Page: " + s + " \n" +
"Google Page: " + g + "\n" +
"Ethereum Page: " + e + "\n")
.andThen(System.out::println);
engine.run(plan);
}
}
Output:
StackOverFlow Page: 149
Google Page: 13097
Ethereum Page: 152
This example is fully asynchronous. The home pages for StackOverflow ,
Google, and Ethereum are all fetched in parallel while the original
thread has returned to the calling code. We used Tasks.par to tell the
engine to parallelize these HTTP requests. Once all of the responses
have been retrieved they are transformed into a int (string
length)that is finally printed out.
Gist: https://gist.github.com/vishwaratna/26417f7467a4e827eadeee6923ddf3ae
beacause you use the same task to run.
Task is interface , and the abstract class is BaseTask which contains the filed "_stateRef", this filed maintain the task status.
first run the task in the INIT status, when the first has excute. status change to RUN.
in this code prevent the task excute.
com.linkedin.parseq.BaseTask#contextRun
has a judgement:transitionRun(traceBuilder).
soļ¼the right way to excute the code is follow:
private void replayOkHttpNotExecuteSecondTask() {
try {
log.info("begin task");
engine.blockingRun(okHttpTask());
engine.blockingRun(okHttpTask());
} catch (Exception e) {
e.printStackTrace();
}
}
private Task okHttpTask() {
OkHttpClient okHttpClient = new OkHttpClient();
return Task.async(() -> {
SettablePromise<String> settablePromise = Promises.settable();
Request request = new Request.Builder().url("http://baidu.com").build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
System.out.println("error");
}
#Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
settablePromise.done(response.body().string());
}
});
return settablePromise;
}).map("map to length", content -> content.length())
.andThen(System.out::println);
}
I am trying to write to a local variable inside a JSONObjectRequest. Here is my code:
JsonObjectRequest get_id_request = new JsonObjectRequest(Request.Method.GET, URL_ID, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
boolean load_full_data = false;
try {
JSONObject jsonNotificationID = response.getJSONObject("n");
int notificationID = jsonNotificationID.getInt("id");
// Change flag to get full preferences below
if(notificationID > currentNotificationID) {
load_full_data = true;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onErrorResponse(VolleyError error) {
}
});
I want to be able to check the server, if there are new IDs (different to the ones already stored in shared Preferences), then download the new ones. So to do this, I want to set my variable load_full_data = true, then further down (oustide this request):
// Get the IDs, see if they are different.
volleyQueue.add(get_id_request);
if(load_full_data) {
Log.d(TAG, "run: Load Full Data");
volleyQueue.add(get_full_request);
}
Only thing is, I cant reference a local variable inside my JSONObjectRequest. It says it needs to final. How can I pass data in and out of this?
You could create a new class and let it implement the interface whose definition you would like to enrich, in your case Response.Listener<JSONObject>
I am not familiar with this API but an example code would be like:
class MyResponseListener implements Response.Listener<JSONObject> {
boolean isGoodParam;
MyResponseListener(boolean isGoodParam) {
this.isGoodParam = isGoodParam;
}
public isGoodParam() {
return this.isGoodParam;
}
#Override
public void onResponse(JSONObject response) {
//use your param
if(this.isGoodParam) {
doStuff();
}
}
}
then your client code would be:
boolean initialIsGood = true;
MyResponseListener listener = new MyResponseListener(initialIsGood);
JsonObjectRequest getIdRequest = new JsonObjectRequest(Request.Method.GET, URL_ID, null, listener,
Response.ErrorListener { error ->
// TODO: Handle error
});
//outside of the listener, assuming that the status of the boolean changed and you want to find out the new value
boolean newValue = listener.isGoodParam();
Cosmetic note: Please stick to the code convention standards, makes the code more readable. (for example camelCases and no_snakes :)
After reading MANY posts that seem similar, these were all about JSON requests, not StringRequests.
I am using volley API for my Android application, and I am following a tutorial on interaction between my app using volley and my server which is handled with php.
For some reason however, my data is not sent to the php part, because when I try to access the data on the webserver, it states that the variables are empty.
Here is my project. First off is my Singleton class which sets up ONE requestqueue:
import android.content.Context;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
public class Server_singleton
{
private static Server_singleton anInstance;
private RequestQueue requestQueue;
private static Context aCtx;
private Server_singleton(Context context)
{
aCtx = context;
requestQueue = getRequestQueue();
}
public static synchronized Server_singleton getInstance(Context context)
{
if(anInstance == null)
{
anInstance = new Server_singleton(context);
}
return anInstance;
}
public RequestQueue getRequestQueue()
{
if(requestQueue == null)
{
requestQueue = Volley.newRequestQueue(aCtx.getApplicationContext());
}
return requestQueue;
}
public <T> void addToRequestQueue(Request<T> request)
{
requestQueue.add(request);
}
}
This above class should be all nice and fine I believe(99% certain), since I follow a general design approach recommended by Android/Google using volley.
Secondly, the next file which uses Server_singleton. Here is where the magic happens, and most likely the mistake is in here some place:
import android.content.Context;
import android.util.Log;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import java.util.HashMap;
import java.util.Map;
/**
*
*
* This class handles requests to web server by using Google Volley API
* Google Volley API is very powerful and abstracts many low-level details when establishing
* connection with a web server.
* Volley API does not run on the main thread, which is the correct way of doing it in android.
* If it was not doing work in a background thread, the main thread would be blocked(perhaps).
* This is all done in an asynchronous way, which means that methods may behave somewhat
* different than you would expect. A method which returns a string for example
* may return a null object, before it is actually done waiting on the response from server
* This means that we have to introduce callback methods with for instance interfaces.
*/
public class Server_interaction
{
String server_url = "http://hiddenfromyou/update_location.php"; //correct ip in my code, but hidden here
String response_string;
RequestQueue queue;
Context context;
public Server_interaction(Context context)
{
this.context = context;
queue = Server_singleton.getInstance(context).getRequestQueue();
}
public static final String TAG = Server_interaction.class.getSimpleName();
public void post_request(final VolleyCallback callback)
{
StringRequest stringRequest = new StringRequest(Request.Method.POST, server_url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response)
{
response_string = response;
callback.onSuccess(response_string);
//requestQueue.stop();
Log.i(TAG, "the response is: "+ response_string);
}
}
, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error){
response_string = "Something went wrong";
//error.printstacktrace()
//requestQueue.stop();
Log.i(TAG, "something went wrong. Is the server up and running?");
}
})
{
#Override
protected Map<String, String> getParams() throws AuthFailureError {
String the_name = "olaf";
String the_mail = "lalalal";
String the_country = "Norway";
String the_latitude = "33";
String the_longitude = "99";
Map<String, String> params = new HashMap<String, String>();
params.put("name", the_name);
params.put("email", the_mail);
params.put("country", the_country);
params.put("latitude", String.valueOf(the_latitude));
params.put("longitude", String.valueOf(the_longitude));
Log.i(TAG, "inside getparams : "+params);
return params;
}
};//stringrequest parameter end
//add request to requestqueue
Log.i(TAG, "the stringrequest: "+ stringRequest);
Server_singleton.getInstance(context).addToRequestQueue(stringRequest);
Log.i(TAG, "the response again:: "+ response_string);
}
}
The above code WORKS. But it should POST country, latitute etc to my webserver...
Here is my PHP script:
<?php
$email = isset($_POST["email"]) ? $_POST["email"] : print("received nothing!"); //receive from android app
$phonenumber = $_POST["phonenumber"]; //receive from android app
$country = $_POST["country"]; //receive from android app
$latitude = $_POST["latitude"]; //receive from android app
$longitude = $_POST["longitude"];
$username_for_localhost = "root";
$password_for_localhost = "";
$host = "localhost";
$db_name = "exigentia_location_db";
$con = mysqli_connect($host, $username_for_localhost, $password_for_localhost, $db_name);
if($con)
{
echo "Connection succeded";
}
else
{
echo "Connection failed";
}
$sql = "insert into person values('".$email."', '".$phonenumber."', '".$country."', '".$location."', '".$latitude."', '".$longitude."');";
if(mysqli_query($con, $sql))
{
echo "data insertion succeeded";
}
else
{
echo "data insertion failed";
}
mysqli_close($con);
?>
I check only the first var if its set, and else print out. It prints out the text, which means it is not set...Also the other ones give me index errors, since they obviously are empty...
What am I doing wrong? I have been fiddling with this problem for days, and I cannot figure out where I am wrong.
Finally a pic of what happens when I refresh my page with the php script after running the app:
try this:
Server_singleton.getInstance().addToRequestQueue(request, method);
where method is your tag: like "Register", "login" ..etc.You can use without Tag method also.
Now in your Server_singleton write this code:
public class Server_singleton extends Application {
public static final String TAG = Server_singleton.class.getSimpleName();
private RequestQueue mRequestQueue;
private static Server_singleton mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized Server_singleton getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
Make sure you set the permission in manifest:
<uses-permission android:name="android.permission.INTERNET" />
And in build.gradle use:
compile 'com.mcxiaoke.volley:library-aar:1.0.0'
put("Content-Type", "application/x-www-form-urlencoded")
http://www.itworld.com/article/2702452/development/how-to-send-a-post-request-with-google-volley-on-android.html
You need to also override the getBodyContentType() like getParams() and put the following code in it.
#Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded; charset=UTF-8";
}
The picture you have shown depicts that there may be errors in your PHP script. The $ sign may not be present with the variables used in the script, or any other scripting errors cause such UI to appear as a result of running php script.
I have a project where you can ask for resources that are served by jax-rs in the json format. Everything works properly in the browser when I query the rest URL the json appears.
Now I want my GWT project to request those resources and process them and show them in my interface. The simplest way I found to do so is using a request builder and an overlay. Code is lower. The problem is, it seems when the code is running it never goes into the actual RequestCallback(). The status string is never changed. I thought it could be a SOP so I added the <add-linker name="xs"/> but still doesn't work. Any ideal?
package com.workoutcell.client;
//import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.http.client.*;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
/**
*
* #author
*/
public class RestToInfoSession{
String queryReturn = null;
JsArray<InfoJSO> arrayOfInfo = null;
String host = "http://localhost:8080/mysite";
String restModule = "/calendar/getinfo";
String id = null;
String year = null;
String month = null;
String status = "Not Initialized";
public RestToInfoSession(String id, String year, String month){
this.id =id;
this.year = year;
this.month = month;
String url = host + restModule + "/"+this.id + "/"+this.year + "/"+this.month;
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
try {
status = "Initialized at Url " + builder.getUrl();
Request request = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
// Couldn't connect to server (could be timeout, SOP violation, etc.)
status = "Error on connecting to Server";
}
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
// arrayOfInfo = jsonToJsArray(response.getText());
status = "JSON has been Fetched. Result is:" + response.getText();
} else if(0 == response.getStatusCode()) {
status = "Error is 0";
} else {
status = "Error in JSON Request:" + response.getStatusCode();
//response.getStatusText();
}
}
});
} catch (RequestException ex) {
status = "Error in Request Builder Startup";
}
}
//get an jso object in array
private final native JsArray<InfoJSO> jsonToJsArray(String json) /*-{
return eval(json);
}-*/;
public JsArray<InfoJSO> getInfoArray (){
return arrayOfInfo;
}
}
UPDATE: My problem is the same as Referring to a non-final variable data inside an inner class . I wasn't aware of asynchronous calls working mechanism. I still don't know how to pass my response.getText() to update a label that isn't part of my RestToInfoSession class any ideas?
Consider using the RestyGWT project. It will make calling JAXRS JSON resources as easy as using GWT-RPC. Plus you can typically reuse the same request response DTOs from the server side on the client side.
I have put a timer that checks every 1000ms if my json string has updated from null to the xhttp requested data. This works, but I got a feeling there is a more elegant way of resolving this problem.