How to mock new Builder with some new objects as parameters
default RestTemplate restTemplate(String baseUrl, Optional<Map<String, String>> headers) {
return new RestTemplateBuilder()
.requestFactory(
() -> new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()))
.uriTemplateHandler(new DefaultUriBuilderFactory(baseUrl))
.interceptors(new RequestResponseLoggingInterceptor(headers))
.errorHandler(new CustomResponseErrorHandler())
.build();
}
I tried spying, but its not working
RestTemplateService restTemplateService = Mockito.spy(RestTemplateService.class);
RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
when(restTemplateService.restTemplate(anyString(), any())).thenReturn(restTemplate);
Related
I am trying to call below API from my SpringBoot Application:
"https://api.coindesk.com/v1/bpi/currentprice.json"
Since this API is returning javaScript instead of Json is am getting error as :
no suitable HttpMessageConverter found for response type [class ] and content type [application/javascript].
kindly advise how resolve this issue. Below is my code:
package org.digital.cur.service;
public class DigitalCurService
{
public static ResponseEntity digitalCurService1()
{
final HttpHeaders headers= setHttpHeaders();
RestTemplate restTemplate = new RestTemplate();
HttpEntity<String> request= new HttpEntity<>(headers);
ResponseEntity<Currentprice> responseEntity = restTemplate.exchange("https://api.coindesk.com/v1/bpi/currentprice.json", HttpMethod.GET, request, Currentprice.class );
return responseEntity;
}
private static HttpHeaders setHttpHeaders()
{
HttpHeaders headers = new HttpHeaders();
MediaType mt = new MediaType("application", "javascript");
headers.setContentType(mt);
return headers;
}
}
I am following this spring integration example - https://github.com/iainporter/spring-file-poller
#Bean
public IntegrationFlow writeToFile(#Qualifier("fileWritingMessageHandler") MessageHandler fileWritingMessageHandler) {
return IntegrationFlows.from(ApplicationConfiguration.INBOUND_CHANNEL)
.transform(m -> new StringBuilder((String)m).reverse().toString())
.handle(fileWritingMessageHandler)
.log(LoggingHandler.Level.INFO)
.get();
}
#Bean (name = FILE_WRITING_MESSAGE_HANDLER)
public MessageHandler fileWritingMessageHandler(#Qualifier(OUTBOUND_FILENAME_GENERATOR) FileNameGenerator fileNameGenerator) {
FileWritingMessageHandler handler = new FileWritingMessageHandler(inboundOutDirectory);
handler.setAutoCreateDirectory(true);
handler.setFileNameGenerator(fileNameGenerator);
return handler;
}
Controller example
#PostMapping(value ="/data/{id}")
public String load( #RequestParam("jsonFile") MultipartFile jsonFile,
#PathVariable("id") Long id) throws JsonMappingException, JsonProcessingException{
//some business logic
return "Controller is called";
}
Instead of simple handling, I want to call a Rest endpoint that expects a file.
i.e. calling a rest api in handler similar to fileWritingMessageHandler
https://github.com/spring-projects/spring-integration-samples/blob/261648bed136a076f76ed15b1017f5e5b6d8b9ae/intermediate/multipart-http/src/main/resources/META-INF/spring/integration/http-outbound-config.xml
How can I create Map
Map<String, Object> multipartMap = new HashMap<String, Object>();
multipartMap.put("jsonFile", ????);
and call a getway method like
HttpStatus postMultipartRequest(Map<String, Object> multipartRequest);
To send a multi-part request you need to have a payload as a Map<String, Object>. You can read files from a directory using FileReadingMessageSource and respective poller configuration: https://docs.spring.io/spring-integration/docs/current/reference/html/file.html#file-reading. This one emits messages with java.io.File as a payload. To create a Map for it you just need a simple transformer in Java DSL:
.<File, Map<String, File>>transform(file -> Collections.singletonMap("jsonFile", file))
and then you use standard .handle(Http.outboundChannelAdapter("/data/{id}").uriVariable("id", "headers.someId")): https://docs.spring.io/spring-integration/docs/current/reference/html/http.html#http-java-config
I have an API with 2 different response:
response OK
{ "name": "test" }
response KO
[
{
"name_1": "test",
"name_2": "test"
}
]
the problem is that using Retrofit, normally, I use a model to parse results but response KO has not an array name.
How can I create a model? (I cannot change the API)
So to add another POJO you can do this:
private static Gson gson = new GsonBuilder()
.registerTypeAdapter(Model1.class, new GsonDeserializer<Model1>())
.registerTypeAdapter(Model2.class, new GsonDeserializer<Model2>())
//or create a POJO for the names array of Model2
.registerTypeAdapter(Model2.class, new GsonDeserializer<Names>())
Where GsonDeserializer is a custom serializer that can be defined, like:
public class GsonDeserializer<T> implements JsonDeserializer<T> {
#Override
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject el = json.getAsJsonObject();
return new Gson().fromJson(el, typeOfT);
}
And then in your Retrofit client you just add:
retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
I have a class which invokes a rest service using resttemplate.
Class MyService{
RestTemplate resttemplate = new RestTemplate();
public void handler(){
string token;
token = restTemplate.exchange(authurl, HttpMethod.POST, getHttpEntity(tenantLogin, basicAuth), String.class)
.getBody();
}
private static <T> HttpEntity<T> getHttpEntity(T jsonRequest, String authorization) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", authorization);
return new HttpEntity<T>(jsonRequest, headers);
}
}
For above my test class is as below.
Class restTemplateTest{
RestTemplate restTemplate = mock(RestTemplate.class);
Field fieldReflectionUtil =
ReflectionUtils.findField(Myservice.class, "restTemplate");
ReflectionUtils.makeAccessible(fieldReflectionUtil);
ReflectionUtils.setField(fieldReflectionUtil, handler, restTemplate);
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
List<String> payload = new ArrayList<>();
when(restTemplate.exchange(Mockito.anyString(), Mockito.<HttpMethod> eq(HttpMethod.POST),
Mockito.eq(new HttpEntity<>(payload.toString(), headers)), Mockito.<Class<Object>> any()).getBody())
.thenReturn(Mockito.anyString());
}
restemplate getbody() is giving nullpointer exception.
Is there something wrong in the way resttemplate is mocked.
Thanks,
Anjana.
You are supposed to return some dummy string or json string.
String token="$11234qwer";
when(restTemplate.exchange(Mockito.anyString(), Mockito.<HttpMethod>
eq(HttpMethod.POST),
Mockito.eq(new HttpEntity<>(payload.toString(), headers)), Mockito.<Class<Object>>
any()).getBody()).thenReturn(token);
I'm writing a java program to access hadoop jobhistory service to retrieve some information.
I'm using HTTPClient to make the HttpGet call. I need to login from a keytab file (I have the file on my ~/.ssh/ folder) instead of type in user name and password.
My question is: How to login from keytab in HTTPClient?
Here is how I set up my HTTPClient
System.setProperty("java.security.krb5.conf", "krb5.conf");
System.setProperty("sun.security.krb5.debug", "true");
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
System.setProperty("java.security.krb5.realm", prop.getProperty("krb5.realm"));
System.setProperty("java.security.krb5.kdc", prop.getProperty("krb5.kdc"));
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(100);
//TODO login from keytab ?
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("DUMMY", null));
Lookup<AuthSchemeProvider> authRegistry = RegistryBuilder.<AuthSchemeProvider>create()
.register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory())
.build();
httpClient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider)
.setDefaultAuthSchemeRegistry(authRegistry)
.setConnectionManager(cm)
.build();
HttpResponse response = httpClient.execute(request);
One interesting is this code can run successfully in my IntelliJ. But After I build and run it from command line, it will show up the info to ask me for username and password.
I'm new to authentication, hope somebody can help. Thanks a lot.
HttpClientBuilder builder = HttpClientBuilder.create();
Lookup<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create()
.register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true)).build();
builder.setDefaultAuthSchemeRegistry(authSchemeRegistry);
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(null, -1, null), new Credentials() {
#Override
public Principal getUserPrincipal() {
return null;
}
#Override
public String getPassword() {
return null;
}
});
builder.setDefaultCredentialsProvider(credentialsProvider);
final HttpClient httpClient = builder.build();
final Subject subj = new Subject();
Krb5LoginModule krb5 = new Krb5LoginModule();
Map<String, String> options = new HashMap<>();
options.put("doNotPrompt", "true");
options.put("storeKey", "true");
options.put("useKeyTab", "true");
options.put("useTicketCache", "true");
options.put("keyTab", keytabFilePath); //Path to keytab file
options.put("principal", principal); //Principal name
options.put("debug", "true");
krb5.initialize(subj, null, null, options);
krb5.login();
krb5.commit();
HttpResponse response = Subject.doAs(subj, new PrivilegedExceptionAction<HttpResponse>() {
#Override
public HttpResponse run() throws Exception {
return httpClient.execute(request);
}
});