So I have an application which pulls information from an API using retrofit as the library. I thought I had it all working but whenever I run the application I get a null pointer exception and the app crashes and I'm unsure why:
The interface that builds retrofit:
public interface FriendsAPI {
static final String URL = "https://www.cs.kent.ac.uk/";
#GET("https://www.cs.kent.ac.uk/people/staff/iau/LocalUsers.php")
Call<User> getFriends();
class Factory {
private static FriendsAPI service;
public static FriendsAPI getInstance() {
if (service == null) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(URL)
.build();
return service;
} else {
return service;
}
}
}
}
Stores the JSON array into a list:
public class FriendsInfo {
#SerializedName("Users")
#Expose
private List<User> Users = new ArrayList<User>();
/**
*
* #return
* The Users
*/
public List<User> getUsers() {
return Users;
}
/**
*
* #param Users
* The Users
*/
public void setUsers(List<User> Users) {
this.Users = Users;
}
}
Finally where I'm calling it (and the code that triggers the fatal exception, although I don't know why):
public void populateFriends(){
FriendsAPI.Factory.getInstance().getFriends().enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
String tempLat = response.body().getLat();
String tempLon = response.body().getLon();
tLat = Double.parseDouble(tempLat);
tLon = Double.parseDouble(tempLon);
}
#Override
public void onFailure(Call<User> call, Throwable t) {
Log.e("Failed :(",t.getMessage());
}
});
}
I think I've included all the relevant code but if there is anything missing I can post it here. I also have a more complete version of the project on Github.
Thanks in advance guys.
You have not written anything to service inside getInstance(). Hence it is always null. You need to assign the retrofit.create() object to service.
public static FriendsAPI getInstance() {
if (service == null) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(URL)
.build();
service = retrofit.create(FriendsAPI.class); //Add this line
return service;
} else {
return service;
}
}
}
} else {
return service;
}
}
If service is null you return null, change it like this
class Factory {
private static MyApiEndpointInterface service;
if (service == null) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(URL)
.build();
service=retrofit.create(FriendsApi.class);
return service;
} else {
return service;
}
}
}
Related
I am trying to test my Service class that uses Retrofit to make #GET call.
I updated my test case and now I am using the mock-retrofit from square to mock the server following their test sample and some other examples here. But I am struggling to unit test the method that calls the retrofit interface.
The sample example of retrofit-mock tests the interface class. How can I mock the retrofit call for my method that implements the interface method.
public class XmattersApi {
private XmattersInterface service;
public GroupsResponse getGroupsWithSupervisor() throws IOException {
String host = xmattersApiConfiguration.getHost();
Interceptor interceptor = new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder().addHeader("Authorization", "TestToken").build();
return chain.proceed(newRequest);
}
};
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.interceptors().add(interceptor);
OkHttpClient client = builder.build();
Retrofit retrofit = new Retrofit.Builder()
.baseurl(getBaseUri(host).toUriString())
.addConverterFactory(JacksonConverterFactory.create())
.client(client)
.build();
service = retrofit.create(XmattersInterface.class);
Call<GroupsResponse> retrofitCall = service.getGroupsWithSupervisor("supervisors");
Response<GroupsResponse> response = retrofitCall.execute();
if (!response.isSuccessful()) {
throw new IOException(response.errorBody() != null
? response.errorBody().string(): "unknown error");
}
return response.body();
}
}
My interface class defined below:
public interface XmattersInterface {
#Headers({"Content-type: application/json;charset=UTF-8"})
#GET("groups")
Call<GroupsResponse> getGroupsWithSupervisor(#Query("embed") String embed);
}
I have tried mocking the retrofit call and returning the mocked response when the service interface is called.
It is not calling the mock. Here is my updated test case.
public class XmattersApiTest {
XmattersApi xmattersAPi;
XmattersInterfaceMock xmattersInterfaceMock;
private final NetworkBehavior behavior = NetworkBehavior.create();
#BeforeEach
public void setUp() throws Exception {
Retrofit retrofit = new Retrofit.Builder()
.addCallAdapterFactory(JacksonConverterFactory.create())
.baseUrl("http://example.com").build();
MockRetrofit mockRetrofit = new MockRetrofit.Builder(retrofit).networkBehavior(behavior).build();
final BehaviorDelegate<XmattersInterface> delegate = mockRetrofit.create(XmattersInterface.class);
xmattersInterfaceMock = new XmattersInterfaceMock(delegate);
}
#Test
void testGroupsWithSupervisorCase_1() throws IOException {
Call<GroupsResponse> call = mock(Call.class);
XmattersInterface xmattersInterface = mock(XmattersInterface.class)
Call<GroupsResponse> mockCall = xmattersInterfaceMock.getGroupsWithSupervisor("supervisors");
Response<GroupsResponse> mockResponse = mockCall.execute; // Mock data is received here from the XmattersInterfaceMock
when(xmattersInterface.getGroupsWithSupervisor(ArgumentMatchers.anyString())).thenReturn(mockCall);
when(call.execute()).thenReturn(mockResponse)
xmattersApi.getGroupsWithSupervisor(); //Fails with java.net.SocketTimeoutException error
}
}
The service mock class to delegate the request:
public class XmattersInterfaceMock implements XmattersInterface {
private final BehaviorDelegate<XmattersInterface> delegate;
public XmattersInterfaceMock(BehaviorDelegate<XmattersInterface> delegate) {
this.delegate = delegate;
}
#Override
public Call<GroupsResponse> getGroupsWithSupervisor(String embed) {
return delegate.returningResponse(getMockGroupsResponse()).getGroupsWithSupervisor(embed);
}
}
What am I doing wrong here? Someone please help!
I am using Springboot- JUnit, mockito
Helloc
I am trying to create webscoket endpoint using Spring WebFlux. I want this endpoint to return some events.
In order to do so I created ConnectableFlux of events and in handle(..) method I map it to Flux. But after I give it to WebSocketSession, nothing happens - websocket client doesn't receive anything. But at the same time println(event.toString()) which you can see in my handle(..) method below actually prints information to console.
Could you please tell what am I missing?
public class EventWebsocketHandler implements WebSocketHandler {
// constructors and etc.
#Override
public Mono<Void> handle(WebSocketSession session) {
ObjectMapper objectMapper = new ObjectMapper();
Flux<WebSocketMessage> messages = eventService.events()
.flatMap(event -> {
try {
System.out.println(event.toString());
return Mono.just(objectMapper.writeValueAsString(event));
} catch (JsonProcessingException e) {
return Mono.error(e);
}
})
.map(session::textMessage);
return session.send(messages);
}
#Service
public class EventService {
List<EventDto> events = new ArrayList<>();
private final Flux<EventDto> eventFlux = Flux.<EventDto>create(fluxSink -> {
while (true) {
if (!events.isEmpty()) {
fluxSink.next(events.get(0));
events.remove(0);
}
}
})
.publish()
.autoConnect();
public void push(EventDto event) {
events.add(event);
}
public Flux<EventDto> events() {
return eventFlux;
}
}
I have another WebSocketHandler in my project and it works fine, which means everything is OK with configuration:
public class MyWebSocketHandler implements WebSocketHandler {
#Override
public Mono<Void> handle(WebSocketSession session) {
Flux<Long> source = Flux.interval(Duration.ofMillis(1000 * 3));
return session.send(source.map(l -> session.textMessage(String.valueOf(l))));
}
}
This
private final Flux<EventDto> eventFlux = Flux.<EventDto>create(fluxSink -> {
while (true) {
if (!events.isEmpty()) {
fluxSink.next(events.get(0));
events.remove(0);
}
}
})
.publish()
.autoConnect();
Has to be replaces with this
private final Sinks.Many<EventDto> processor = Sinks.many().multicast().onBackpressureBuffer();
I wanted to load a json, one after one, beacause its large JsonArray. before then i used Retrofit call and Its oKey, but the output take too long. Any help on how to implement it this way is appreciated.
ApiInterface.java
public interface ApiInterface {
#POST("/token/login")
Call<User> login(#Body Login login);
#Streaming
#GET("/api/schools/")
Observable<ResponseBody> getAllSchools(#Header("Authorization") String authToken);
}
Client.java
public class Client {
public static final String BASE_URL = "site.net";
private static Retrofit retrofit;
public static Retrofit getClient(){
if (retrofit == null){
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
return retrofit;
}
}
ApiInterface apiInterface = Client.getClient().create(ApiInterface.class);
String tok = "Token " + token;
apiInterface.getAllSchools(tok)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ResponseBody>() {
#Override
public void onSubscribe(Disposable disposable) {
}
#Override
public void onNext(ResponseBody responseBody) {
//fetch json one after one.
Toast.makeText(getContext(), responseBody.toString(), Toast.LENGTH_SHORT).show();
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onComplete() {
Toast.makeText(getContext(), "finish--", Toast.LENGTH_SHORT).show();
}
});
MasterService.java
// MasterService.java
public interface MasterService {
#GET("userMaster")
Call<List<UserMaster>> getUsers();
#GET("farmerMaster")
Call<List<FarmerMaster>> getfarmers();
#GET("orgnMaster")
Call<List<OrgnMaster>> getOrgns();
#GET("cropMaster")
Call<List<CropMaster>> getCrops();
#POST("farmerPost")
Call<FarmerMaster> createPost(#Body FarmerMaster farmerMaster);
}
MasterRepository.java
// MasterRepository.java
public class MasterRepository {
MasterDao masterDao;
MasterService masterService;
List<UserMaster> userMasters;
List<FarmerMaster> farmerMasters;
List<CropMaster> cropMasters;
List<OrgnMaster> orgnMasters;
/**
* Constructor
* #param application application context
* Get the instance of AppDatabase(Local database) and Retrofit(Service)
* */
public MasterRepository(Application application) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("http://192.168.1.50/MEPLSERVICES/API/")
.build();
masterService =retrofit.create(MasterService.class);
}
/**
* #return All the UserMaster info as a List
* */
public List<UserMaster> getUserMasters(){
try {
Call<List<UserMaster>> call = masterService.getUsers();
call.enqueue(new Callback<List<UserMaster>>() {
#Override
public void onResponse(Call<List<UserMaster>> call, Response<List<UserMaster>> response) {
if (!response.isSuccessful()) {
return;
}
List<UserMaster> userMasters = response.body();
for(UserMaster userMaster:userMasters){
System.out.println(userMaster);
}
}
#Override
public void onFailure(Call<List<UserMaster>> call, Throwable t) {
}
});
}catch(Exception e){
System.out.println(">>>>>>>>>>>>>"+e);
}
return userMasters;
}
}
// While hitting the Url http://192.168.1.50/MEPLSERVICES/API/userMaster, i get the json request as follows
```javascript
[{"empID":"1","empName":"admin","empType":"admin","password":"admin","fullName":"Anandaraj","designation":"administator","department":"admin","empCode":"10001","mobileNumber":"8939803008","emailAddress":"admin#admin.com"},{"empID":"35","empName":"h","empType":"Admin","password":"s","fullName":"s","designation":"Manager","department":"Marketing","empCode":"xy12","mobileNumber":"345","emailAddress":"est#test.com"}]
** When i call getUserMasters method of MasterRepository Class , call.enqueue not being called..
Dependencies
//RetroFit
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
Thank you in advance!
I just implemented the retrofit android library for rest api call but it is not working and has no error. My code is
ApiInterface.java
public interface ApiInterface {
#POST("url")
void getLoginResponse(#Field("username") String username , #Field("password") String password,
#Field("clientId") String clientId , Callback<LoginResponse> cb);
}
RestClient.java
public class RestClient {
private static ApiInterface REST_CLIENT;
private static String BASE_URL = "base_url";
static {
setupRestClient();
}
private RestClient() {}
public static ApiInterface get() {
return REST_CLIENT;
}
private static void setupRestClient() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(BASE_URL)
.build();
REST_CLIENT = restAdapter.create(ApiInterface.class);
}
}
and in activity i call
RestClient.get().getLoginResponse(usernameText, passwordText, clientId, new Callback<LoginResponse>() {
#Override
public void success(LoginResponse loginResponse, Response response) {
Toast.makeText(getApplicationContext(), loginResponse.getToken(), Toast.LENGTH_SHORT).show();
}
#Override
public void failure(RetrofitError error) {
}
});
And in AndroidManifest i set the permission for internet.
How to make RestClient as a singleton:
public class RestClient {
private static ApiInterface REST_CLIENT;
private static String BASE_URL = "base_url";
public RestClient() {}
public static ApiInterface getInstance() {
//if REST_CLIENT is null then set-up again.
if (REST_CLIENT == null) {
setupRestClient();
}
return REST_CLIENT;
}
private static void setupRestClient() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(BASE_URL)
.build();
REST_CLIENT = restAdapter.create(ApiInterface.class);
}
}
Then when you wanna call api you should always call:
ApiInterface api = RestClient.getInstance();
api.callWhatApiYouWant
I am answering late but it will be useful for others, I preferred to use retrofit 2.
// Retrofit
compile 'com.squareup.retrofit2:retrofit:2.1.0'
// JSON Parsing
compile 'com.google.code.gson:gson:2.7'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
Quit Simple to create instance.
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
Here is Detailed explanation about retrofit 2 android best example and quit simple to understand.
http://al-burraq.com/retrofit-android-get-and-post-api-request-tutorial/