I am trying to build an Android App that implements a Collaborative Filtering Algorithm using Retrofit 2,Realm and The Movie Database API.
When making my Retrofit callback, onResponse returns a successful status code (200), but from logging I get that my response.body().getResults returns null. I'm in this pickle now and I can't get it to work.My ApiService seem to be working fine and I make other retrofit callbacks to get directors,movies by title,movies by release date.Anyways, here is some code snippets that might be helpful.
APIService.java
package com.yannis.thesis.movierecommendationapp.api;
import com.yannis.thesis.movierecommendationapp.models.DirectorResponse;
import com.yannis.thesis.movierecommendationapp.models.GenreResponse;
import com.yannis.thesis.movierecommendationapp.models.Movie;
import com.yannis.thesis.movierecommendationapp.models.MovieResponse;
import com.yannis.thesis.movierecommendationapp.models.PrimaryMovieInfo;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface APIService {
#POST("/list")
Call<Movie> loadMovie();
#GET("movie/top_rated")
Call<MovieResponse> getTopRatedMovies(#Query("api_key") String apiKey);
#GET("movie/popular")
Call<MovieResponse> getPopularMovies(#Query("api_key") String apiKey);
#GET("movie/{id}")
Call<MovieResponse> getMovieDetails(#Path("id") int id, #Query("api_key") String apiKey);
#GET("search/movie")
Call<MovieResponse> getMovieByTitle(#Query("query") String title, #Query("api_key") String apiKey);
}
MovieResponse.java
package com.yannis.thesis.movierecommendationapp.models;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class MovieResponse {
#SerializedName("page")
private Integer page;
#SerializedName("results")
private List<Movie> results;
#SerializedName("total_results")
private Integer totalResults;
#SerializedName("total_pages")
private Integer totalPages;
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public List<Movie> getResults() {
return results;
}
public void setResults(List<Movie> results) {
this.results = results;
}
public Integer getTotalResults() {
return totalResults;
}
public void setTotalResults(Integer totalResults) {
this.totalResults = totalResults;
}
public Integer getTotalPages() {
return totalPages;
}
public void setTotalPages(Integer totalPages) {
this.totalPages = totalPages;
}
}
MovieRecommendationApp.java
package com.yannis.thesis.movierecommendationapp;
import android.app.Application;
import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import com.luseen.logger.LogType;
import com.luseen.logger.Logger;
import com.weiwangcn.betterspinner.library.BetterSpinner;
import com.yannis.thesis.movierecommendationapp.activities.BaseActivity;
import com.yannis.thesis.movierecommendationapp.activities.MainActivity;
import com.yannis.thesis.movierecommendationapp.api.APIService;
import com.yannis.thesis.movierecommendationapp.models.DirectorResponse;
import com.yannis.thesis.movierecommendationapp.models.DirectorResult;
import com.yannis.thesis.movierecommendationapp.models.Genre;
import com.yannis.thesis.movierecommendationapp.models.GenreResponse;
import com.yannis.thesis.movierecommendationapp.models.MainPagerEnum;
import com.yannis.thesis.movierecommendationapp.models.Movie;
import com.yannis.thesis.movierecommendationapp.models.MovieResponse;
import com.yannis.thesis.movierecommendationapp.models.MovieRecommendedForUser;
import com.yannis.thesis.movierecommendationapp.models.Recommendation;
import com.yannis.thesis.movierecommendationapp.models.User;
import com.yannis.thesis.movierecommendationapp.models.UserRatesMovie;
import com.yannis.thesis.movierecommendationapp.MovieRecommendationApp;
import com.yannis.thesis.movierecommendationapp.R;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmQuery;
import io.realm.RealmResults;
import io.realm.Sort;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MovieRecommendationApp extends Application {
private static MovieRecommendationApp instance;
public BaseActivity lastActivity;
String API_BASE_URL = "http://api.themoviedb.org/3/";
private final static String API_KEY = "******************";
private static Retrofit retrofitinstance;
private String loggedInUserId;
private Realm realm;
final Double SIMILARITY_PILLOW = 0.5;
final Double PREDICTION_PILLOW = 3.0;
private APIService client;
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(
GsonConverterFactory.create()
);
Retrofit retrofit =
builder
.client(
httpClient.build()
)
.build();
retrofit2.Call<MovieResponse> call;
#Override
public void onCreate() {
super.onCreate();
instance = this;
Realm.init(this);
RealmConfiguration config = new RealmConfiguration.Builder()
.name("myrealmDB.realm")
.deleteRealmIfMigrationNeeded()
.build();
Realm.setDefaultConfiguration(config);
new Logger.Builder()
.isLoggable(BuildConfig.DEBUG)
.logType(LogType.WARN)
.tag("Iamerror")
.build();
realm = Realm.getDefaultInstance();
MovieRecommendationAlgorithm();
}
public static MovieRecommendationApp getInstance() {
return instance;
}
public static Retrofit getRetrofitInstance() {
return retrofitinstance;
}
public static String getApiKey() {
return API_KEY;
}
public void MovieRecommendationAlgorithm() {
prediction("activeUserId","637",neighbours);
}
public void prediction(String activeUserId, String notYetRatedMovieId,ArrayList<String> neightbours) {
Double activeAVG = avgRating(activeUserId);
Double A = 0.0;
Double B = 0.0;
for (int i = 0; i < neightbours.size(); i++) {
avgRating(neightbours.get(i));
A = A + similarity(activeUserId, neightbours.get(i)) * (getUser_i_MovieRating(neightbours.get(i), notYetRatedMovieId) - avgRating(neightbours.get(i)));
B = B + similarity(activeUserId, neightbours.get(i));
}
final Double prediction = activeAVG + A / B;
if (prediction < PREDICTION_PILLOW) {
return;
}
int movieId = Integer.parseInt(notYetRatedMovieId);
client = retrofit.create(APIService.class);
call = client.getMovieDetails(movieId, MovieRecommendationApp.getApiKey());
call.enqueue(new retrofit2.Callback<MovieResponse>() {
#Override
public void onResponse(retrofit2.Call<MovieResponse> call, retrofit2.Response<MovieResponse> response) {
int statusCode = response.code();
if (response.isSuccessful() == false) {
Logger.w("unsuccessful w status", String.valueOf(statusCode));
} else {
//problem is in this spot
Logger.w( " reponse body is " + response.body().getResults());
}
// Logger.e("Number of movies received: " + movies.size());
}
#Override
public void onFailure(retrofit2.Call<MovieResponse> call, Throwable t) {
}
});
}
}
I double checked the API call using Postman - calling https://api.themoviedb.org/3/movie/637?api_key=*********&language=en-US
got me the desired JSON Body.
Thank you for you time and help.
I don't know if this will be helpfull, but here: if (response.isSuccessful() == false)
It's a quite strange compare a boolean method isSuccessful() with false, the method already return a boolean.
After searching at the movie database api forum , I found this [https://www.themoviedb.org/talk/5667650ec3a36836970002bc][1]
in which it is stated that "The only way we currently support is via query parameters." and there is a big possibility for my problem to be related with the fact that I am using a #Path parameter and not a #Query parameter.
So now the million dollar question is how to convert the
#GET("movie/{id}")
Call<MovieResponse> getMovieDetails(#Path("id") int id, #Query("api_key") String apiKey);
to a Call using the #Query annotation.
Related
So Im writing unit test a class that does bankId authentication and the unit test looks like this.
package se.kt.client;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.HttpEntity;
import se.kt.common.vo.PublicApplicationForm;
import se.kt.models.BankIdAuthRequest;
import se.kt.models.BankIdAuthResponse;
import se.kt.models.BankIdCollectResponse;
import static org.mockito.ArgumentMatchers.any;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
#RunWith(MockitoJUnitRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class BankIdClientTest {
private final RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
#InjectMocks
private BankIdClient bankIdClient;
#BeforeEach
public void setUp() {
}
#Test
public void testBankIdAuthentication_success() throws InterruptedException {
PublicApplicationForm form = new PublicApplicationForm();
form.setSsn("123456-7890");
form.setIp_address("123.123.123.123");
BankIdAuthRequest authRequest = bankIdClient.authRequestFromApplicationForm(form, "123");
BankIdAuthResponse authResponse = new BankIdAuthResponse();
authResponse.setOrderRef("123456");
BankIdCollectResponse collectResponse = new BankIdCollectResponse();
collectResponse.setStatus("completed");
Mockito.when(restTemplate.postForEntity(anyString(), any(HttpEntity.class), any()))
.thenReturn(ResponseEntity.ok(authResponse));
Mockito.when(restTemplate.getForEntity(anyString(), any()))
.thenReturn(ResponseEntity.ok(collectResponse));
assertTrue(bankIdClient.bankIdAuthentication(authRequest));
}
}
And the class Im testing looks like this:
package se.kt.client;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import se.kt.common.domain.AbstractApplicationForm;
import se.kt.common.vo.PublicApplicationForm;
import se.kt.models.BankIdAuthRequest;
import se.kt.models.BankIdAuthResponse;
import se.kt.models.BankIdCollectResponse;
import javax.validation.constraints.AssertFalse;
import javax.validation.constraints.AssertTrue;
import java.util.Objects;
#Component
public class BankIdClient {
private static final Logger log = LoggerFactory.getLogger(BankIdClient.class);
private final RestTemplate customRestTemplate;
private static final String CONTENT_TYPE = "Content-Type";
#Value("${BankId.AuthUrl}")
private String bankIdAuthUrl;
#Value("${BankId.CollectUrl}")
private String bankIdCollectUrl;
#Value("${BankId.SecretKey}")
private String bankIdSecretKey;
public BankIdClient(RestTemplate customRestTemplate) {
this.customRestTemplate = customRestTemplate;
}
public BankIdAuthRequest authRequestFromApplicationForm(PublicApplicationForm form, String jobId) {
BankIdAuthRequest bankIdAuthRequest = new BankIdAuthRequest();
bankIdAuthRequest.setPno(form.getSsn());
bankIdAuthRequest.setIpAddress(form.getIp_address());
bankIdAuthRequest.setRefID(jobId);
bankIdAuthRequest.setSecretKey(bankIdSecretKey);
bankIdAuthRequest.setAvsikt("Kt application");
return bankIdAuthRequest;
}
public boolean bankIdAuthentication(BankIdAuthRequest bankIdAuthRequest) throws InterruptedException {
//Setup header and body for request.
HttpHeaders headers = new HttpHeaders();
headers.add(CONTENT_TYPE, MediaType.APPLICATION_JSON.toString());
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
try {
String bankIdAuthFormJson = ow.writeValueAsString(bankIdAuthRequest);
HttpEntity<String> httpEntity = new HttpEntity<>(bankIdAuthFormJson, headers);
ResponseEntity<BankIdAuthResponse> authResponse = customRestTemplate.postForEntity(bankIdAuthUrl, httpEntity, BankIdAuthResponse.class);
bankIdCollectUrl += Objects.requireNonNull(authResponse.getBody()).getOrderRef();
ResponseEntity<BankIdCollectResponse> collectResponse;
do {
collectResponse = customRestTemplate.getForEntity(bankIdCollectUrl, BankIdCollectResponse.class);
Thread.sleep(1500);
if (Objects.requireNonNull(collectResponse.getBody()).getStatus().equals("completed"))
return true;
if (Objects.requireNonNull(collectResponse.getBody()).getStatus().equals("failed"))
return false;
} while (Objects.requireNonNull(collectResponse.getBody()).getStatus().equals("progress"));
} catch (JsonProcessingException e) {
log.info(e.getMessage());
} catch (NullPointerException e) {
log.info(e.toString());
log.info("BankId API not responding correctly. Check server connection");
}
return false;
}
public void cancelBankIdAuthentication(#Value("${BankId.CancelUrl}") String bankIdCancelUrl) {
customRestTemplate.postForEntity(bankIdCancelUrl, null, String.class);
}
}
Now for some reson this line:
ResponseEntity<BankIdAuthResponse> authResponse = customRestTemplate.postForEntity(bankIdAuthUrl, httpEntity, BankIdAuthResponse.class);
keeps producing the result authResponse = null indicating that
Mockito.when(restTemplate.postForEntity(anyString(), any(HttpEntity.class), any()))
.thenReturn(ResponseEntity.ok(authResponse));
is not working. Now I have been playing around with this for over 3h and i still get the same result. What could i be doing wrong?
#InjectMocks only works with #Mock-annotated fields, not with fields which get assigned a manually created mock. Therefore you need to change:
private final RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
#InjectMocks
private BankIdClient bankIdClient;
to
#Mock
private RestTemplate restTemplate;
#InjectMocks
private BankIdClient bankIdClient;
I also recommend reading Why is my class not calling my mocked methods in unit test? which provides additional insights and points out some common mistakes when using Mockito or mocks in general.
hi guys i have been trying to integrate sdk of an android pos machine which comes with inbult printer to my react native app.Since the sdk is native i use bridging . But i am not able to print the data even after i follow the documents .
leaving the code i tried
import android.content.res.AssetManager;
import android.printservice.PrintService;
import android.provider.Settings;
import android.text.Layout;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.zcs.sdk.DriverManager;
import com.zcs.sdk.Printer;
import com.zcs.sdk.SdkResult;
import com.zcs.sdk.print.PrnStrFormat;
import com.zcs.sdk.print.PrnTextFont;
import com.zcs.sdk.print.PrnTextStyle;
import com.zcs.sdk.util.LogUtils;
import java.io.IOException;
import java.io.InputStream;
public class CustomModule extends ReactContextBaseJavaModule {
private static ReactApplicationContext reactContext;
DriverManager mDriverManager= DriverManager.getInstance();
Printer mPrinter = mDriverManager.getPrinter();
CustomModule(ReactApplicationContext context) {
super(context);
reactContext = context;
}
#ReactMethod
public void show() {
int printStatus = mPrinter.getPrinterStatus();
System.out.println(mPrinter);
PrnStrFormat format = new PrnStrFormat();
format.setTextSize(30);
mPrinter.setPrintAppendString(" -----------------------------", format);
mPrinter.setPrintAppendString(" ", format);
mPrinter.setPrintAppendString(" ", format);
mPrinter.setPrintAppendString(" ", format);
mPrinter.setPrintAppendString(" ", format);
printStatus = mPrinter.setPrintStart();
Toast.makeText(reactContext, "Hi from Android"+"here", Toast.LENGTH_LONG).show();
}
#ReactMethod
public void getDeviceId(Promise promise) {
try {
String android_id = Settings.Secure.getString(reactContext.getContentResolver(),
Settings.Secure.ANDROID_ID);
promise.resolve(android_id);
} catch (Exception e) {
promise.reject("Error", e);
}
}
#NonNull
#Override
public String getName() {
return "ABC";
}
}
please let know if anyone has an idea
I am trying to assert output of the below transformed response from sling servlet filter. I am not able to get hold of output response and not able to assert.
import com.day.cq.wcm.api.Page;
import com.safeway.app.rxwa.pharmacy.utils.HttpServletResponseCopier;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.engine.EngineConstants;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/**
* This filter rewrites link for the Content Fragment list model exporter
*/
#Component(service = Filter.class,
immediate = true,
configurationPolicy = ConfigurationPolicy.REQUIRE,
property = {
EngineConstants.SLING_FILTER_SCOPE + "=" + EngineConstants.FILTER_SCOPE_REQUEST,
EngineConstants.SLING_FILTER_METHODS + "=GET",
EngineConstants.SLING_FILTER_PATTERN + "=/content/experience-fragments/rxwa/.*",
EngineConstants.SLING_FILTER_SELECTORS + "=model",
EngineConstants.SLING_FILTER_EXTENSIONS + "=json"})
#Designate(ocd = ContentJsonLinkRewriterFilter.Config.class)
public class ContentJsonLinkRewriterFilter implements Filter {
private static final Logger logger =
LoggerFactory.getLogger(ContentJsonLinkRewriterFilter.class);
private Config config;
private List<String> resourceTypes;
#Reference
private ResourceResolverFactory resolverFactory;
#Activate
public void activate(Config config) {
this.config = config;
this.resourceTypes = Arrays.asList(config.resourceTypes());
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// no-op
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
String resultString = "{}";
// add author check
if (!(response instanceof SlingHttpServletResponse) || !(request instanceof SlingHttpServletRequest)) {
throw new IllegalStateException("Filter not properly registered as Sling Servlet Filter");
}
if (!config.enabled()) {
logger.debug("Filter disabled");
filterChain.doFilter(request, response);
return;
}
SlingHttpServletRequest slingHttpServletRequest = (SlingHttpServletRequest) request;
Resource currentResource = slingHttpServletRequest.getResource();
String currentResourceType = currentResource.getResourceType();
if(currentResource.isResourceType("cq:Page")) {
Page page = slingHttpServletRequest.getResource().adaptTo(Page.class);
currentResourceType = page.getContentResource().getResourceType();
}
String finalProcessResourceType = currentResourceType;
if (resourceTypes.stream().noneMatch(resourceType -> StringUtils.startsWith(finalProcessResourceType, resourceType))) {
logger.debug("Current resource path {} is not configured to be evaluated", currentResourceType);
filterChain.doFilter(request, response);
return;
}
// Wrap Response Class before servlet gets called
HttpServletResponseCopier responseCopier = new HttpServletResponseCopier((SlingHttpServletResponse) response);
filterChain.doFilter(request, responseCopier);
// externalize links after the servlet finishes
responseCopier.flushBuffer();
//read original response
byte[] responseBytes = responseCopier.getCopy();
String responseString = new String(responseBytes, responseCopier.getCharacterEncoding());
if (StringUtils.isNotEmpty(responseString)) {
//replace all links
resultString = responseString.replaceAll(StringUtils.substring(slingHttpServletRequest.getRequestURI(),0, slingHttpServletRequest.getRequestURI().lastIndexOf("/")), "");
}
responseCopier.resetBuffer();
responseCopier.getOutputStream().write(resultString.getBytes());
responseCopier.setContentType("application/json");
responseCopier.setCharacterEncoding("utf-8");
}
#Override
public void destroy() {
// no-op
}
#ObjectClassDefinition(name = "Content Fragment List Link Rewriter Filter",
description = "Configuration for filter to extend Content Fragment List functionality to rewrite links")
public #interface Config {
#AttributeDefinition(name = "Enabled",
description = "If this filter should not be active, rather try to delete this config. " + "Only in cases " +
"where this cannot be easily accomplished uncheck this option to disable the filter.") boolean enabled() default false;
#AttributeDefinition(name = "Resource Types",
description = "Resource Types to be evaluated by the filter.") String[] resourceTypes();
}
}
Unit test I tried
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import com.safeway.app.rxwa.pharmacy.utils.HttpServletResponseCopier;
import io.wcm.testing.mock.aem.junit.AemContext;
import org.apache.commons.io.IOUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.testing.mock.osgi.MapUtil;
import org.apache.sling.testing.mock.sling.loader.ContentLoader;
import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import com.day.cq.commons.jcr.JcrConstants;
import com.day.cq.wcm.api.components.ComponentContext;
import com.day.cq.wcm.api.designer.Design;
import com.day.cq.wcm.api.designer.Designer;
import com.google.common.collect.Sets;
import org.mockito.junit.MockitoJUnitRunner;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
#RunWith(MockitoJUnitRunner.class)
public class ContentJsonLinkRewriterFilterTest {
protected static final String CONTENT_ROOT = "/content/experience-fragments/rxwa";
public Map<String, Object> props = new HashMap<>();
#Rule
public AemContext context = new AemContext();
#Mock
FilterChain chain;
public ContentJsonLinkRewriterFilter filter;
#Before
public void setUp() {
context.load().json("/test-page-content.json", "/content/experience-
fragments/rxwa");
props.clear();
props.put("enabled", "true");
props.put("resourceTypes", new String[] {"rxwa-
pharmacy/components/structure/xfpage"});
ContentJsonLinkRewriterFilter aei = context.registerInjectActivateService(new
ContentJsonLinkRewriterFilter(), props);
filter = Mockito.spy(aei);
}
#Test
public void doFilterCall() throws ServletException, IOException {
context.requestPathInfo().setResourcePath("/content/experience-fragments/rxwa/templated-
page");
context.requestPathInfo().setSelectorString("model");
context.requestPathInfo().setExtension("json");
context.request().setMethod("GET");
context.response().setCharacterEncoding("UTF-8");
context.currentPage("/content/experience-fragments/rxwa/templated-page");
Mockito.doAnswer(invocation -> {
HttpServletResponseWrapper httpServletResponseWrapper =
(HttpServletResponseWrapper) invocation.getArguments()[1];
String testHtmlContent = IOUtils.toString(
ContentLoader.class.getResourceAsStream("/test-page-content.json"),
StandardCharsets.UTF_8
);
httpServletResponseWrapper.getWriter()
.write(testHtmlContent);
httpServletResponseWrapper.getWriter().flush();
return null;
}).when(chain).doFilter(Mockito.any(), Mockito.any());
filter.doFilter(context.request(), context.response(), chain);
Mockito.verify(chain).doFilter(Mockito.any(), Mockito.any());
String testHtmlContent2 = IOUtils.toString(
ContentLoader.class.getResourceAsStream("/test-page-content.json"),
StandardCharsets.UTF_8
);
}
}
I have an Android app where I'm trying to make a GET request to my API using Retrofit2. I have copied some code online that allows me to add the access token to the body of the request as this is how my API is setup. Following the code online, the author is able to call the api variable from a different class but I am unable to.
Here is the class the api variable is defined:
cCustomerService.java
package com.example.dentdevils.helper.retrofit.oauth2.client;
import android.content.Context;
import android.content.SharedPreferences;
import com.example.dentdevils.helper.retrofit.oauth2.OauthConstant;
import com.example.dentdevils.helper.retrofit.oauth2.service.CustomerService;
import java.io.IOException;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
import static com.example.dentdevils.MainActivity.access;
import static com.example.dentdevils.MainActivity.mypreference;
public class cCustomerService {
public final CustomerService api;
private Context mContext;
SharedPreferences sharedPreferences;
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder requestBuilder = request.newBuilder();
mContext.getSharedPreferences(mypreference, Context.MODE_PRIVATE);
RequestBody formBody = new FormBody.Builder()
.add("access_token", sharedPreferences.getString(access, ""))
.build();
String postBodyToString = bodyToString(request.body());
postBodyToString += ((postBodyToString.length() > 0) ? "&" : "") + bodyToString(formBody);
request = requestBuilder.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyToString))
.build();
return chain.proceed(request);
}
}).build();
public static String bodyToString(final RequestBody requestBody) {
try {
final RequestBody copy = requestBody;
final Buffer buffer = new Buffer();
if (copy != null) {
copy.writeTo(buffer);
} else {
return "";
}
return buffer.readUtf8();
} catch (IOException e) {
return "didn't work";
}
}
public cCustomerService() {
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl(OauthConstant.DATA_SERVER_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
api = retrofit.create(CustomerService.class);
}
}
As you can see I set the api variables value at the bottom.
Now I want to access it in the following class:
ViewCustomers.Java
package com.example.dentdevils;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import com.example.dentdevils.helper.retrofit.oauth2.OauthConstant;
import com.example.dentdevils.helper.retrofit.oauth2.client.cCustomerService;
import com.example.dentdevils.helper.retrofit.oauth2.response.CustomerResponse;
import com.example.dentdevils.helper.retrofit.oauth2.service.CustomerService;
import java.io.IOException;
import java.util.List;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import static com.example.dentdevils.MainActivity.access;
import static com.example.dentdevils.MainActivity.mypreference;
import static com.example.dentdevils.helper.retrofit.oauth2.client.cCustomerService.bodyToString;
public class ViewCustomers extends AppCompatActivity {
private Context mContext;
SharedPreferences sharedPreferences;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_customers);
CustomerService customerService = api.create(CustomerService.class);
Call<List<CustomerResponse>> callArray = customerService.getCustomers();
callArray.enqueue(new Callback<List<CustomerResponse>>() {
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onResponse(Call<List<CustomerResponse>> call, retrofit2.Response<List<CustomerResponse>> response) {
if (response.isSuccessful())
{
List<CustomerResponse> customers = response.body();
customers.forEach(customer -> System.out.println(customer.getName()));
} else {
Log.e("TAG", "Failed!");
}
}
#Override
public void onFailure(Call<List<CustomerResponse>> call, Throwable t) {
Log.e("TAG", t.getLocalizedMessage());
}
});
}
}
As you can see I reference the api variable on this line CustomerService customerService = api.create(CustomerService.class); but I get an error saying it cannot resolve symbol 'api'. Like I said the author of the post has his setup exactly like mine so why isn't mine working? I added the relevant imports and I still can't access it. Any help would be appreciated.
I'm building an application with Quarkus and it's vert.x extension. Now I want to build a REST endpoint which should stream all saved addresses. To test this whiout a reactive data source I wan't to create a ArrayList with example addresses and stream them so I can check if my test works. But I don't find how I can stream a collection.
My actual code:
import io.vertx.reactivex.core.Vertx;
import org.reactivestreams.Publisher;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.Collection;
#Path("/addresses")
public class AddressResource {
private Collection<Address> adresses;
#Inject private Vertx vertx;
public AddressResource() {
super();
adresses = new ArrayList<>();
}
#GET
#Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<Address> get() {
Address address = new Address();
address.setStreet("590 Holly Street");
address.setCity("Townsend");
address.setState("Ohio");
address.setZip(6794);
adresses.add(address);
adresses.add(address);
adresses.add(address);
adresses.add(address);
adresses.add(address);
adresses.add(address);
// What to do here?
return null;
}
}
And this is my test:
import io.quarkus.test.junit.QuarkusTest;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import javax.json.bind.JsonbBuilder;
import java.util.ArrayList;
import java.util.List;
import static io.restassured.RestAssured.given;
#QuarkusTest
public class DBServiceTest {
#Test
void testGetAddresses() throws InterruptedException {
given()
.when()
.get("/addresses")
.then()
.statusCode(200)
.body(Matchers.containsInAnyOrder(readTestAdresses().toArray()));
}
private List<Address> readTestAdresses() {
return JsonbBuilder.create()
.fromJson(
this.getClass().getResourceAsStream("test-addresses.json"),
new ArrayList<Address>() {}.getClass().getGenericSuperclass());
}
}
Edit 1:
I tried the following:
#GET
#Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> get() {
Address address = new Address();
address.setStreet("590 Holly Street");
address.setCity("Townsend");
address.setState("Ohio");
address.setZip(6794);
adresses.add(address);
return Flowable.just("Test 1","Test 2","Test 3");
}
And this works. So the problem must have something to do with the address objects.
You can use something like
#GET
#Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> get() {
Address address = new Address();
address.setStreet("590 Holly Street");
address.setCity("Townsend");
address.setState("Ohio");
address.setZip(6794);
return Flowable.just(address, address, address,....).map(a -> yourToString(a));
}
Where yourToString is a method that will create the proper string representation (json perhaps).
I could fix it, I missed a dependency:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jsonb</artifactId>
</dependency>
And had to convert my objects to json manually and so on change the return type to Publisher<String>:
import io.reactivex.Flowable;
import io.vertx.core.json.Json;
import org.reactivestreams.Publisher;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.Collection;
#Path("/addresses")
#Consumes(MediaType.APPLICATION_JSON)
public class AddressResource {
private Collection<Address> addresses;
public AddressResource() {
super();
addresses = new ArrayList<>();
}
#GET
#Produces(MediaType.SERVER_SENT_EVENTS)
public Publisher<String> get() {
Address address = new Address();
address.setStreet("590 Holly Street");
address.setCity("Townsend");
address.setState("Ohio");
address.setZip(6794);
addresses.add(address);
return Flowable.fromIterable(addresses).map(Json::encode);
}
}
Also my test was wrong, this is how it looks like now:
import io.quarkus.test.common.http.TestHTTPResource;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import javax.json.bind.JsonbBuilder;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.sse.SseEventSource;
import java.net.URL;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import static org.assertj.core.api.Assertions.assertThat;
#QuarkusTest
public class DBServiceTest {
#TestHTTPResource("/addresses")
private URL enpointUrl;
#Test
#DisplayName("Get all addresses")
void testGetAddresses() {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(String.valueOf(enpointUrl));
try (SseEventSource source = SseEventSource.target(target).build()) {
CompletableFuture<Collection<Address>> futureAddresses = new CompletableFuture<>();
Set<Address> foundAddresses = new HashSet<>();
source.register(
event -> {
if (!foundAddresses.add(
event.readData(Address.class, MediaType.APPLICATION_JSON_TYPE))) {
futureAddresses.complete(foundAddresses);
}
},
Assertions::fail);
source.open();
Collection<Address> addresses = futureAddresses.join();
assertThat(addresses).containsExactlyInAnyOrderElementsOf(readTestAdresses());
}
}
private List<Address> readTestAdresses() {
return JsonbBuilder.create()
.fromJson(
this.getClass().getResourceAsStream("test-addresses.json"),
new ArrayList<Address>() {}.getClass().getGenericSuperclass());
}
}