NoSuchMethodError using maven [duplicate] - java

I am searching for this error whole internet, but yet, only one stackoverflow entry with no answer or comment.
I am trying to use Retrofit 2. It is my first time using it. Here are my dependencies:
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.google.code.gson:gson:2.6.2'
I exclued any OkHttp libraries as Retrofit already uses it.
This is my request interface:
public interface LoginService {
#POST(HTTPService.AUTHENTICATIO_URL)
Call<User> login();
}
Next: my Service generator:
public class ServiceGenerator {
public static final String API_BASE_URL = HTTPService.BASE_URL;
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public static <S> S createService(Class<S> serviceClass, String username, String password, String roleId) {
if (username != null && password != null) {
String credentials = username+":"+password+":"+roleId;
final String basic =
"Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
httpClient.addInterceptor(chain -> {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", basic)
.header("Accept", "application/json")
.method(original.method(), original.body());
Request request = requestBuilder.build();
return chain.proceed(request);
});
}
OkHttpClient client = httpClient.build();
Retrofit retrofit = builder.client(client).build();
return retrofit.create(serviceClass);
}
}
And next: where I make the request:
#Override
public void loadData(DataSource.LoadJsonCallback loadJsonCallback) {
String login = mUser.getLogin();
String password = mUser.getPassword();
LoginService loginService =
ServiceGenerator.createService(LoginService.class, login, password, "");
Call<User> call = loginService.login();
String a = call.request().url().toString();
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
try {
loadJsonCallback.onTasksLoaded(response.body());
User a = response.body();
mUser = getDataFromJson("");
if (mUser != null) {
mUser.setPassword(password);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<User> call, Throwable t) {
loadJsonCallback.onDataNotAvailable(t.getMessage());
}
});
}
So, I get this exception, that I cannot find anywhere:
java.lang.NoSuchMethodError: No virtual method newJsonReader(Ljava/io/Reader;)Lcom/google/gson/stream/JsonReader; in class Lcom/google/gson/Gson; or its super classes (declaration of 'com.google.gson.Gson' appears in /data/app/org.ucomplex.ucomplex-2/base.apk)
Thank you for any help.

I started using the newer versions:
compile 'com.google.code.gson:gson:2.7'
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
And the error disappeared.

Related

How to get the Plain Text error message thrown by Post request using Retrofit 2 in Android?

So I have this POST request made to the server and based on an argument the server will return error message within the errorBody() of Retrofit. I am trying to handle that Plain Text error returned by the server and then display it to the user within my Android application which uses Java. Below is my current attempt but this is giving me this error in Logcat:
#Url cannot be used with #POST URL (parameter #1)
Here is 400 response from the server:
Interface:
public interface ChangePickLocationClient
{
#GET
Call<ResponseBody> checkItem(#Url String url, #Header("Authorization") String authToken);
#GET
Call<String> getStringError(#Url String url, #Header("Authorization") String authToken);
#POST("Pick/ChangePickLocationAcceptChange")
Call<String> changePickLocationPOST(#Url String url, #Header("Authorization") String authToken, #Body
ChangePickLocationPostModel changePickLocationPostModel);
}
Implementation:
private static final String BASE_URL = "http://00.00.00.1234/api/";
Gson mGson = new Gson();
Retrofit retrofit = new Retrofit.Builder().client(new OkHttpClient())
.baseUrl(BASE_URL).addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(mGson))
.build();
ChangePickLocationClient ChangePickLocationClient =
retrofitPOST.create(ChangePickLocationClient.class);
String itemNumber = itemNumberValue.getText().toString();
newPickLocationValue.setText(newPickLocationValue.getText().toString().toUpperCase());
String newPickLocation = newPickLocationValue.getText().toString();
String token = globalClass.getActiveToken();
final ChangePickLocationClient mChangePickLocationInterface =
retrofit.create(ChangePickLocationClient.class);
Call<String> mCallErrorPOST = mChangePickLocationInterface.changePickLocationPOST
(postUrl, "Bearer " + globalClass.getActiveToken(),
changePickLocationPostModel);
call.enqueue(new Callback<ChangePickLocationPostModel>()
{
#Override
public void onResponse(Call<ChangePickLocationPostModel> call,
Response<ChangePickLocationPostModel> response)
{
String mPlainTextResponse = null;
try {
if(response.errorBody() != null)
{
mPlainTextResponse = response.errorBody().string();
}
} catch (IOException e)
{
e.printStackTrace();
}
Toast.makeText(ChangePickLocation.this, mPlainTextResponse
,Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<ChangePickLocationPostModel> call, Throwable t)
{
Toast.makeText(ChangePickLocation.this, "Unknown server error!"
,Toast.LENGTH_SHORT).show();
}
});
When the response is 400, the second call being made needs to be a clone() call. This is because the Call cannot be used more than once as stated in the documentation.
use this:
call.clone().enqueue(new Callback<ChangePickLocationPostModel>()
instead of
call.enqueue(new Callback<ChangePickLocationPostModel>()

to call the retrofit in different classes

I am a beginner to the android. I am using Retrofit to call the API. But I would like to write the retrofit call method only once and use the same function in different API calls in my application. I try to create It's a generic method in nonactivity class and use it in my activity class.
public static generic_Retrofit_Class apiClient;
private Retrofit retrofit = null;
public static generic_Retrofit_Class getInstance() {
if (apiClient == null) {
apiClient = new generic_Retrofit_Class();
}
return apiClient;
}
public Retrofit getclient()
{
return getclient(null);
}
private Retrofit getclient(Object o) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.level(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();
okHttpClient.readTimeout(60, TimeUnit.SECONDS);
okHttpClient.writeTimeout(60, TimeUnit.SECONDS);
okHttpClient.connectTimeout(60, TimeUnit.SECONDS);
okHttpClient.addInterceptor(interceptor);
okHttpClient.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
return chain.proceed(request);
}
});
retrofit = new Retrofit.Builder()
.baseUrl(Constant.Baseurl)
.client(okHttpClient.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
After this code when I call this method in my Activity class it shows an error. Here is the implementation of the method in the Activity class.
private void Getstock() {
final String mid = medicineid.getText().toString().trim();
final String batch = batchno.getText().toString().trim();
if (medicineid.getText().length() != 0 && batchno.getText().length() != 0) {
App_Interfaces app_interfaces = (App_Interfaces) new generic_Retrofit_Class().getclient().create(App_Interfaces.class);
Map<String, String> mapdata = new HashMap<>();
mapdata.put("mid", mid);
mapdata.put("batch", batch);
final Call<Response> getstock_call = app_interfaces.getstock(mapdata);
getstock_call.enqueue(new Callback<Response>() {
#Override
public void onResponse(Call<Response> call, Response<Response> response) {
if (response.isSuccessful() && response.body() != null && response != null) {
String jsonresponse = response.body().toString();
parseStockData(jsonresponse);
System.out.print(jsonresponse);
return;
}
}
#Override
public void onFailure(Call<Response> call, Throwable t) {
}
});
}
Here is the error
java.lang.IllegalArgumentException: 'retrofit2.Response' is not a valid response body type. Did you mean ResponseBody?
for method App_Interfaces.getstock
here is my Interface Code
public interface get_stock
{
#GET("/getstock")
Call<Response> getstock(#QueryMap Map<String, String> options);
}
Welcome to SO
Change the getClient method code as
public class YOUR_CLASS{
private static YOUR_API_INTERFACE retrofit = null;
public static YOUR_API_INTERFACE getClient() { // no need to pass the object params
if(retrofit == null){
//you client code same as you written in question
retrofit = new Retrofit.Builder()
.baseUrl(Constant.Baseurl)
.client(okHttpClient.build()) //okHtttpClient from your client code
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit.create(YOUR_API_INTERFACE.class);
}
}
Now, you can easily access the retrofit api interface by YOUR_CLASS.getClient(). This will return your Retrofit Interface
Your Retrofit Interface with declare method should be like this
public interface YOUR_API_INTERFACE {
#GET("your api name")
Call<YOUR_POJO> yourApi();
}
In your activity/fragment class you can access the yourApi method as
YOUR_CLASS.getClient().yourApi();

How to add bearer token to retrofit request in Java

Hi Im trying to add a bearer token to a retrofit call in java, but i cant seem to pass it.
Currently Im logging in with one method and this creates a bearer token and im trying to add the token to the Get Call, but its just returning a 401 error, have I added the token to the call correctly?
#GET("diagnosis/configuration")
Call<ResponseBody> getFavourites (#Query("favourite") Boolean fave,#Header("Bearer Token") String authHeader);
#POST("auth/login")
Call<LoginResponse> postLogin (#Body LoginCredentialsBody body);
public class LoginApiStepDefinition extends TestBaseFix {
Retrofit retrofit = super.buildRetrofit(super.buildOkHttpClient());
RetrofitCallsLogin call = retrofit.create(RetrofitCallsLogin.class);
RetrofitCallsGetFavourites favecall = retrofit.create(RetrofitCallsGetFavourites.class);
private Response<LoginResponse> responseBody;
private String favouritesResponseBody;
String usernameValue;
String passwordValue;
#And("I login with {string} and {string} to return login token")
public void iLoginWithAndToReturnLoginToken(String username, String password) throws Exception {
LoginApi(username, password);
}
public String LoginApi(String username, String password) throws Exception {
usernameValue = username;
passwordValue = password;
//gets fixture ids for the dates
LoginCredentialsBody login = new LoginCredentialsBody();
login.setPassword(passwordValue);
login.setUsername(usernameValue);
String responseBody = call.postLogin(login).execute().body().toString();
String requiredString = responseBody.substring(responseBody.indexOf("=") + 1, responseBody.indexOf(","));
System.out.println(requiredString);
return token;
}
#Then("I get the list of favourites with {string} and {string}")
public void iGetTheListOfFavouritesWithAnd(String username, String password) throws Exception {
String favouritesResponseBody = favecall.getFavourites(true, LoginApi(username, password)).execute().body().toString();
System.out.println(favouritesResponseBody);
}
}
To add bearer token in retrofit, you have to create a class that implements Interceptor
public class TokenInterceptor implements Interceptor{
#Override
public Response intercept(Chain chain) throws IOException {
//rewrite the request to add bearer token
Request newRequest=chain.request().newBuilder()
.header("Authorization","Bearer "+ yourtokenvalue)
.build();
return chain.proceed(newRequest);
}
}
Now add your Interceptor class in OKHttpClient object and add that obejct in Retrofit object:
TokenInterceptor interceptor=new TokenInterceptor();
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl("add your url here")
.addConverterFactory(JacksonConverterFactory.create())
.build();
these three class will be your final setup for all types of call
for first call(Login) you do not need to pass token and after login pass jwt as bearer token to authenticate after authentication do not need to pass
public class ApiUtils {
private static final String BASE_URL="https://abcd.abcd.com/";
public ApiUtils() {
}
public static API getApiService(String token){
return RetrofitClient.getClient(BASE_URL,token).create(API.class);
}}
2.Using ApiUtils.getapiService you can get the client ,pass jwt or bearer token
public class RetrofitClient {
public static Retrofit retrofit=null;
public static Retrofit getClient(String baseUrl, String token){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(60,TimeUnit.SECONDS)
.connectTimeout(60,TimeUnit.SECONDS)
.addInterceptor(interceptor)
.addInterceptor(new Interceptor() {
#NotNull
#Override
public Response intercept(#NotNull Chain chain) throws IOException {
Request request=chain.request().newBuilder()
.addHeader("Authorization", "Bearer " + token)
.build();
return chain.proceed(request);
}
}).build();
if(retrofit==null||token!=null){
retrofit= new Retrofit.Builder()
.baseUrl(baseUrl)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}}
3 In this Interface you can create methods for get or post requests
public interface API {
#POST("/Api/Authentication/Login")
Call<JsonObject> login(#Body Model userdata);
#POST("/api/Authentication/ValidateSession")
Call<JsonObject> validateSession(#Body MyToken myToken);
#POST("/api/master/abcd")
Call<JsonObject> phoneDir(#Body JsonObject jsonObject);
#Multipart
#POST("/api/dash/UploadProfilePic")
Call<JsonObject> uploadProfile(#Part MultipartBody.Part part);
#FormUrlEncoded
#POST("/api/dashboard/RulesAndPolicies")
Call<JsonObject> rulesAndProcess(#Field("ct") int city);
#FormUrlEncoded
#POST("/api/dashboard/RulesAndPolicies")
Call<JsonObject> rulesAndProcess(
#Field("city") int city,
#Field("department") String department,
#Field("ctype") String ctype
);

Convert Java object into JSON array for Retrofit call

I need to send an array of Strings using a Retrofit call. To do that I decided to create an object like this one:
public class SendEmailsList {
ArrayList<String> emails;
public SendEmailsList(ArrayList<String> emails) {
this.emails = emails;
}
}
And my JSON String must be like this:
{
"emails": ["email#server.com","email1#server.com","email2#server.com"]
}
This is the POST method defined in my interface:
#POST("/v2/companies/{companyId}/invite")
Call<ArrayList<String>> inviteMembers(#Path("companyId") String companyId, #Body SendEmailsList emails);
And this is the method that makes the Retrofit call:
public void SendNetworkRequest() {
OkHttpClient.Builder okhttpBuilder = new OkHttpClient.Builder();
okhttpBuilder.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder newRequest = request.newBuilder().header("Authorization", "Bearer " + token);
return chain.proceed(newRequest.build());
}
});
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(BuildConfig.ENDPOINT)
.client(okhttpBuilder.build())
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
CompanyService invite = retrofit.create(CompanyService.class);
Call<ArrayList<String>> call = invite.inviteMembers("5602eb7ce49c9cd70409f206", new SendEmailsList(invitedEmails));
call.enqueue(new Callback<ArrayList<String>>() {
#Override
public void onResponse(Call<ArrayList<String>> call, Response<ArrayList<String>> response) {
System.out.println("Internal Users: " + response.code());
}
#Override
public void onFailure(Call<ArrayList<String>> call, Throwable t) {
// Log error here since request failed
Log.e("Internal Users Activity", t.toString());
}
});
}
But I am getting this error:
12-21 14:36:49.953 27953-27953/com.construct.test E/Internal Users Activity: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
How can I figure out what is going on?

Make a GET and POST service call with Retrofit with the use of Protobuf (Protocol Buffer)

Can anyone please give me some example how we can use protobuf in retrofit - I tried but its failed with some error , let me give you a sample of my implementation on that.
I hope you guys will help me.
ApiInterface.java
public interface ApiInterface {
#GET
Call<CommonProto.Country> makeGetRequest(#Url String url);
}
ApiClient.java
public class ApiClient {
public static final String BASE_URL = "**************************";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(Proto3ConverterFactory.create())
.build();
}
return retrofit;
}
}
MainActivity.java
ApiInterface apiService =
ApiClient.getClient().create(ApiInterface.class);
Call<CommonProto.Country> call = apiService.makeGetRequest("Services/CountryServices/GetAllCountry");
call.enqueue(new Callback<CommonProto.Country>() {
#Override
public void onResponse(Call<CommonProto.Country> call, Response<CommonProto.Country> response) {
String bodyString = null;
try {
Log.e("RETROFIT ::::::: ", String.valueOf(response.body())+"TEST");
} catch (Exception e) {
Log.e("RETROFIT ERROR ::::::: ", e.getMessage()+"TEST");
e.printStackTrace();
}
}
#Override
public void onFailure(Call<CommonProto.Country> call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
}
);
when i run this way i got the error
java.lang.RuntimeException: com.google.protobuf.InvalidProtocolBufferException: Protocol message tag had invalid wire type.
my Proto.java file and also have Proto.proto file both are here in this link,
https://drive.google.com/folderview?id=0B4loQuzINvHCRUlNbk5LUXE1NXM&usp=sharing
Please let me know how to do this GET Req and also I was Struggling with POST Req.
you can create interface like this
public interface LoginInterface {
#FormUrlEncoded
#POST("url goes here")
Call<LoginResponseData> getUserLoginDeatail(#FieldMap Map<String, String> fields);
}
make an instance of retro file and call interface method something like this
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("base url")
.build();
webApis = retrofit.create(WebApis.class);
Call<LoginResponseData> call = webApis.getCurrentRide(keyValue);
call.enqueue(new Callback<LoginResponseData>() {
#Override
public void onResponse(Call<LoginResponseData> call, Response<LoginResponseData> response) {
try {
} catch (Exception e) {
// customizedToast.showToast(context.getResources().getString(
// R.string.exception));
e.printStackTrace();
}
}
#Override
public void onFailure(Call<LoginResponseData> call, Throwable t) {
}
});
for protocol buffer you can find a reference here

Categories