In the java 15 project I have file application.properties of yml type:
NetanyaInfo:
HydrantPoints: https://www.data.com/
I need to use suiteUrlin in the function:
public String getHydrantPoints() throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create(suiteUrl))//here
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
return response.body();
}
My question is how to get suiteUrl value from the java function?
If this is spring-boot, you do not need anything "special", it will be done for you under the hood. What you do is:
define that application.properties/yaml in src/main/resources
inject that value (almost) anywhere you want
For example:
#Value("${tridelInfo.siteUrl}")
private String siteUrl;
or even inside any bean, via a constructor:
#Bean/#Service/#Component
public class YourBean {
private final String siteUrl;
public YourBean(#Value("${tridelInfo.siteUrl}") String siteUrl) {
this.siteUrl = siteUrl;
}
}
Under the hood, you actually need to define a PropertySourcesPlaceholderConfigurer, but spring-boot does that for you.
There are some options available for this in spring. You can use any of them.
Injecting org.springframework.core.env.Environment to your bean.
#Autowired
private Environment env;
...
public String getTridelSuites() throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create(env.getProperty("suiteUrl");))//here
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
return response.body();
}
Related
I'm writing custom annotation processor and got struggling with code elements' positions.
Imagine I have the code:
public class DummyStepClass {
#Step
public void getInfo() throws Exception {
HttpClient client = HttpClient.newBuilder().build();
#Remember("REQUEST") HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.GET()
.build();
#Remember("RESPONSE") HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}
Purpose of annotation is to save variable into context of a program flow through my steps.
Context class:
public class Context {
private static final HashMap<String, Object> storage = new LinkedHashMap<>();
private Context() {}
public static void save(String k, Object v) {
storage.put(k, v);
}
}
Literally I want to achieve invoking Context.save(k, v); when annotated rather than writing it every time.
So as a result I want to have something like this:
public class DummyStepClass {
#Step
public void getInfo() throws Exception {
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.GET()
.build();
Context.save("REQUEST", request);
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
Context.save("RESPONSE", request);
System.out.println(response.statusCode());
System.out.println(response.body());
}
}
I do generate this lines of code and they appears in .class files. However this two statements are added in the end of a method.
How can I handle this?
I've managed to make this work by hooking into "blocks" of java code and pasting my code at the end.
I am using java.net.http.HttpClient in my Java Spring Boot app and I noticed this weird behaviour.
When my code call HTTP request to 3rd party API, next request to different 3rd party API returns always as bad request (400). When I execute this request first, it works just fine.
When I restart the app, first API call is always successful, but second one is always bad and so I have to call it again after some timeout and then it work.
So I was thinking, if there is any form of "cache" that remember previous settings or whatever from previous request, because second request to different API is always bad. When I inspected HttpRequest in debugger, it seems okay to me and there was nothing really different from the one that worked.
Here is my bean config
#Configuration
public class HttpClientBean {
#Bean
public HttpClient httpClient() {
return HttpClient.newHttpClient();
}
}
HttpRequest builder
public static HttpRequest buildGetRequest(final String url) {
return HttpRequest.newBuilder()
.uri(URI.create(url))
.GET()
.build();
}
public static HttpRequest buildPostRequest(final String url, final String body) {
return HttpRequest.newBuilder()
.version(HttpClient.Version.HTTP_1_1)
.uri(URI.create(url))
.setHeader(CONTENT_TYPE, APPLICATION_JSON)
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
}
and here is HttpService
#Service
public class HttpServiceImpl implements HttpService {
private final HttpClient httpClient;
#Autowired
public HttpServiceImpl(final HttpClient httpClient) {
this.httpClient = httpClient;
}
#Override
public HttpResponse<String> sendGetRequestWithParams(final String url, final String params) throws Exception {
final HttpRequest request = buildGetRequest(url, params);
return httpClient.send(request, HttpResponse.BodyHandlers.ofString());
}
#Override
public HttpResponse<String> sendGetRequestWithoutParams(final String url) throws Exception {
final HttpRequest request = buildGetRequest(url);
return httpClient.send(request, HttpResponse.BodyHandlers.ofString());
}
#Override
public HttpResponse<String> sendPostRequestWithBody(final String url, final String body) throws Exception {
final HttpRequest request = buildPostRequest(url, body);
return httpClient.send(request, HttpResponse.BodyHandlers.ofString());
}
}
Thank you for your advices.
I would like to use a global header for all my requests. Therefore I have implemented the following class:
public class HeaderInterceptor {
public Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.method("GET", null)
.addHeader("Accept", "application/json")
.addHeader("Basic ", "abcdefghi123456789")
.build();
Response response = chain.proceed(request);
return response;
}
}
Now I would like to do the following in the main()-method:
public static void main(String[] args) throws Exception {
OkHttpClient httpClient = new OkHttpClient.Builder().addInterceptor(MyInterceptor).build();
Request reqAllProjects = new Request.Builder()
.url("https://example.com/projects")
.build();
Response resAllProjects = httpClient.newCall(reqAllProjects).execute();
String responseData = resAllProjects.body().string();
System.out.println(responseData);
}
I'm not sure now how to use my HeaderInterceptor. I guess I'll have to enter it here, right?
OkHttpClient httpClient = new OkHttpClient.Builder().addInterceptor(??MyInterceptor??).build();
I tried something like this: addInterceptor(HeaderInterceptor.intercept()) but this is not working...
Can someone help me please? And does the rest of it look fine? Many thanks in advance!
The interceptor class that you have created doesn't seem to be implementing the Interceptor interface. You need to implement as below
public class HeaderInterceptor implements Interceptor {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.addHeader("Accept", "application/json")
.addHeader("Basic ", "abcdefghi123456789")
.build();
Response response = chain.proceed(request);
return response;
}
}
Do note that you should not be modifying the method and body of the request as .method("GET", null) unless you actually need so, as it can result in all the HTTP requests made by the client to make GET requests with null body.
Then add the interceptor while building the client as below
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new HeaderInterceptor()).build();
Have a look at the OkHttp documentation for more info.
Have you checked this question : Okhttp3: Add global header to all requests error
It should be something like
.addInterceptor(new Interceptor())
When my Java web application receives an HTTP POST request, it needs to create a new OkHttp3 Request from the HttpServletRequest and send this to another URL. The original post request could be simple form data or multi-part.
Here's the interface that I am looking to implement:
import okhttp3.Request;
public interface OkHttp3RequestBuilder {
Request create(HttpServletRequest request);
}
Looks like the challenge boils down to how I would create an okhttp3.RequestBody. Here's the relevant part of the implementation...
final HttpUrl targetUrl = HttpUrl.get("http://internal.xyz.com");
final RequestBody requestBody = // ?????
final Request httpRequest = new Request.Builder()
.post(requestBody)
.url(targetUrl)
.build();
return httpRequest;
How do I go about doing it? Any suggestions? Thanks!
This should work, but request.getReader() must never have been called as you can call it only once.
Request create(HttpServletRequest request)
{
final HttpUrl targetUrl = HttpUrl.get("http://internal.xyz.com");
final String originalBody = request.getReader().lines().collect (Collectors.joining (System.lineSeparator()));
final RequestBody requestBody = RequestBody.create(MediaType.parse(request.getContentType()), originalBody);
final Request httpRequest = new Request.Builder()
.post(requestBody)
.url(targetUrl)
.build();
return httpRequest;
}
Thanks for your answer, ETL! This seems to work for me:
#Override
public RequestBody getRequestBody(final HttpServletRequest httpServletRequest) throws IOException {
final InputStream inputStream = httpServletRequest.getInputStream();
final byte[] requestBodyBytes = ByteStreams.toByteArray(inputStream);
final String contentType = httpServletRequest.getContentType();
final MediaType mediaType = MediaType.parse(contentType);
final RequestBody requestBody = RequestBody.create(mediaType, requestBodyBytes);
return requestBody;
}
I am using OAuth and I need to put the OAuth token in my header every time I make a request. I see the #Header annotation, but is there a way to make it parameterized so i can pass in at run time?
Here is the concept
#Header({Authorization:'OAuth {var}', api_version={var} })
Can you pass them in at Runtime?
#GET("/users")
void getUsers(
#Header("Authorization") String auth,
#Header("X-Api-Version") String version,
Callback<User> callback
)
Besides using #Header parameter, I'd rather use RequestInterceptor to update all your request without changing your interface. Using something like:
RestAdapter.Builder builder = new RestAdapter.Builder()
.setRequestInterceptor(new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addHeader("Accept", "application/json;versions=1");
if (isUserLoggedIn()) {
request.addHeader("Authorization", getToken());
}
}
});
p/s : If you are using Retrofit2, you should use Interceptor instead of RequestInterceptor
Since RequestInterceptor is not longer available in Retrofit 2.0
Yes, you can pass them in runtime. As a matter of fact, pretty much exactly as you typed it out. This would be in your API interface class, named say SecretApiInterface.java
public interface SecretApiInterface {
#GET("/secret_things")
SecretThing.List getSecretThings(#Header("Authorization") String token)
}
Then you pass the parameters to this interface from your request, something along those lines: (this file would be for example SecretThingRequest.java)
public class SecretThingRequest extends RetrofitSpiceRequest<SecretThing.List, SecretApiInteface>{
private String token;
public SecretThingRequest(String token) {
super(SecretThing.List.class, SecretApiInterface.class);
this.token = token;
}
#Override
public SecretThing.List loadDataFromNetwork() {
SecretApiInterface service = getService();
return service.getSecretThings(Somehow.Magically.getToken());
}
}
Where Somehow.Magically.getToken() is a method call that returns a token, it is up to you where and how you define it.
You can of course have more than one #Header("Blah") String blah annotations in the interface implementation, as in your case!
I found it confusing too, the documentation clearly says it replaces the header, but it DOESN'T!
It is in fact added as with #Headers("hardcoded_string_of_liited_use") annotation
Hope this helps ;)
The accepted answer is for an older version of Retrofit. For future viewers the way to do this with Retrofit 2.0 is using a custom OkHttp client:
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Builder ongoing = chain.request().newBuilder();
ongoing.addHeader("Accept", "application/json;versions=1");
if (isUserLoggedIn()) {
ongoing.addHeader("Authorization", getToken());
}
return chain.proceed(ongoing.build());
}
})
.build();
Retrofit retrofit = new Retrofit.Builder()
// ... extra config
.client(httpClient)
.build();
Hope it helps someone. :)
Retrofit 2.3.0
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder
.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder newRequest = request.newBuilder().header("Authorization", accessToken);
return chain.proceed(newRequest.build());
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(GithubService.BASE_URL)
.client(okHttpClientBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
I am using this to connect to GitHub.