Call RestApi endpoint resource from EJB - spring-boot

I have been looking around for sample code how to call a Restful service written in Spring boot (deployed in different server/ip) from an EJB client.
I couldn't find a simple example or reference to guide me on how to implement an EJB client that can call a restful service(deployed in different server/ip). Could you please point me to a document or example that shows or describe how the two can interface/talk to each other.
I need to call the endpoint by passing two header parameters for authentication, if authentication is success then only retrieve the details from Rest and send back the response to EJB client.

I use something like this, try
`public void calExternal() throws ProtocolException,
MalformedURLException,
IOException,
NoSuchAlgorithmException,
InvalidKeyException {
URL myurl = new URL("API END POINT URL");
ObjectMapper mapper = new ObjectMapper();
HttpURLConnection conn = (HttpURLConnection) myurl.openConnection();
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
String payLoad = mapper.writeValueAsString("your payload here");
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("AUTHORIZATION-TYPE", "HMAC");
try {
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(payLoad);
wr.flush();
InputStream in = null;
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
in = conn.getInputStream();
} else {
in = conn.getErrorStream();
}
String encoding = conn.getContentEncoding() == null ? "UTF-8" : conn.getContentEncoding();
String response = IOUtils.toString(in, encoding);
} catch (Exception e) {
e.printStackTrace();
}
}

Related

Spring RestTemplate seems to not be thread-safe wrt headers

I have a Spring web client which posts to a Spring web server (the same URL) using two different basic-auth users. Is it a known issue that I can not use a single RestTemplate for both?
When I use a single RestTemplate, and the requests are nearly simultaneous (in different threads), though I specify different users in the header, the receiving server thinks they're from the same user! Note that the request and the headers (and the body of the post) are newly allocated for each request.
It works fine, when I use a single RestTemplate and put a synchronized() around the call to
response = RestTemplate.exchange(url, method, requestParams, MyResponse.class)
I've also tried creating two RestTemplate instances, one for each user - (each built with a RestTemplateBuilder) that works, too. I'll keep this solution, but it surprises me that it's needed.
Is this a known issue?
(I see stackOverflow answers that a RestTemplate is thread-safe after constructed, but the headers are passed in with the request, not as a setting on the already-constructed RestTemplate...)
====
Here's an example of 2 different calls, using 2 different RestTemplates because there were sometimes problems in using the same:
public OperationStatus getOpStatus(String gufi) {
HttpEntity<String> requestParams = new HttpEntity<>(Utils.createBasicHeader(cfg.getManager(), cfg.getManPass()));
ResponseEntity<OperationStatus> restResponse = null;
try {
restResponse = managerRestTemplate.exchange(
cfg.getNussOpApiPath(), HttpMethod.GET, requestParams, OperationStatus.class);
} catch (RestClientException e) {
...
}
OperationStatus opState = restResponse.getBody();
opState.setHttpStatusCode(String.valueOf(restResponse.getStatusCodeValue()));
return opState;
}
Here was a method to do a post, using the priority to switch rest templates (at the time, the target server recognized the priority by the privileges of the user)
UTMRestResponse doPost(Object objToSend, String url, String msg) throws IOException {
String user = cfg.getOpUser();
String pass = cfg.getOpPass();
RestTemplate restTemplate = opUserRestTemplate;
boolean isPriorityOp = false;
if ( objToSend instanceof OpPost) {
OpPost post = (OpPost) objToSend;
String flightNum = post.getFlightNumber();
isPriorityOp = Boolean.TRUE.equals(post.getPriorityOp()); // null is false
} else if ( objToSend instanceof PositionPost) {
PositionPost post = (PositionPost) objToSend;
isPriorityOp = Boolean.TRUE.equals(post.getPriorityOp()); // null is false
}
if (isPriorityOp) {
user = cfg.getUserEmergency();
pass = cfg.getPassEmergency();
restTemplate = emergRestTemplate;
}
String jsonToSend = CommonsObjectMapper.get().writeValueAsString(objToSend);
HttpEntity<String> requestParams = new HttpEntity<>(jsonToSend, Utils.createBasicHeader(user, pass));
UTMRestResponse restResponse = restTemplate.exchange(
url, HttpMethod.POST, requestParams, UTMRestResponse.class).getBody();
if (restResponse.getHttpStatusCode().startsWith("4")) {
String fmt = "Status:{}, url:{}, jsonSent:{}, response:{}";
logger.error(fmt, restResponse.getHttpStatusCode(), url, jsonToSend, restResponse.getMsg());
}
return restResponse;
}

How do I Get current topmost stories using spring boot from http://developer.nytimes.com

How do I Get current topmost stories using spring boot from http://developer.nytimes.com
Want to know how a url can be used to get current story
In order to make a HTTP request from Java, you should use HttpURLConnection. The api of the NYT for top stories is very simple, you should send a GET request to the following URL String url = https://api.nytimes.com/svc/topstories/v2/home.json?api-key=" + apiKey, where apiKey has to be requested from NYT.
The following method does the request and returns the response as a String:
public String getTopStories(String apiKey) throws Exception {
URL url = new URL("https://api.nytimes.com/svc/topstories/v2/home.json?api-key=" + apiKey);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int statusCode = connection.getResponseCode();
if (statusCode != HttpStatus.OK.value()) {
throw new Exception("NYT responded with:" + statusCode);
}
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line+"\n");
}
bufferedReader.close();
return stringBuilder.toString();
}

Why this externa web service call go into error only when the call is performed using Spring RestTemplate?

I am working on a Spring project implementing a simple console application that have to call an external REST web service passing to it a parameter and obtaining a response from it.
The call to this webservice is:
http://5.249.148.180:8280/GLIS_Registration/6
where 6 is the specified ID. If you open this address in the browser (or by cURL tool) you will obtain the expected error message:
<?xml version="1.0" encoding="UTF-8"?>
<response>
<sampleid>IRGC 100000</sampleid>
<genus>Oryza</genus>
<error>PGRFA sampleid [IRGC 100000], genus [Oryza] already registered for this owner</error>
</response>
This error message is the expected response for this request and I correctly obtain it also using cURL tool to perform the request.
So I have to perform this GET request from my Spring application.
To do it I create this getResponse() method into a RestClient class:
#Service
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RestClient {
RestTemplate restTemplate;
String uriResourceRegistrationApi;
public RestClient() {
super();
restTemplate = new RestTemplate();
uriResourceRegistrationApi = "http://5.249.148.180:8280/GLIS_Registration/7";
}
public ResponseEntity<String> getResponse() {
ResponseEntity<String> response = restTemplate.getForEntity(uriResourceRegistrationApi, String.class);
return response;
}
}
Then I call this method from this test method:
#Test
public void singleResourceRestTest() {
System.out.println("singleResourceRestTest() START");
ResponseEntity<String> result = restClient.getResponse();
System.out.println("singleResourceRestTest() END");
}
But I am experiencing a very strange behavior, what it happens is:
1)The call to my external web service seems that happens (I saw it from the web services log).
2) The web service retrieve the parameter having value 7 but then it seems that can't use it as done without problem performing the request from the browser or by the shell statment:
curl -v http://5.249.148.180:8280/GLIS_Registration/7
But now, calling in this way, my webservice (I can't post the code because it is a WSO2 ESB flow) give me this error message:
<200 OK,<?xml version="1.0" encoding="UTF-8"?>
<response>
<error>Location information not correct</error>
<error>At least one between <genus> and <cropname> is required</error>
<error>Sample ID is required</error>
<error>Date is required</error>
<error>Creation method is required</error>
</response>,{Vary=[Accept-Encoding], Content-Type=[text/html; charset=UTF-8], Date=[Fri, 05 May 2017 14:07:09 GMT], Transfer-Encoding=[chunked], Connection=[keep-alive]}>
Looking the web service log it seems that performing the call using RestTemplate it have some problem to use the retrieved ID=7 to perform a database query.
I know it looks terribly strange and you can see: "The problem is of your web service and not of the Spring RestTemplate". This is only partially true because I implemented this custom method that perform a low level Http GET call, this callWsOldStyle() (putted into the previous RestClient class):
public void callWsOldStyle() {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL restAPIUrl = new URL("http://5.249.148.180:8280/GLIS_Registration/7");
connection = (HttpURLConnection) restAPIUrl.openConnection();
connection.setRequestMethod("GET");
// Read the response
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder jsonData = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
jsonData.append(line);
}
System.out.println(jsonData.toString());
}catch(Exception e) {
e.printStackTrace();
}
finally {
// Clean up
IOUtils.closeQuietly(reader);
if(connection != null)
connection.disconnect();
}
}
Using this method instead the RestTemplate one it works fine and this line:
System.out.println(jsonData.toString());
print the expected result:
<?xml version="1.0" encoding="UTF-8"?><response><sampleid>IRGC 100005</sampleid><genus>Oryza</genus><error>PGRFA sampleid [IRGC 100005], genus [Oryza] already registered for this owner</error></response>
To summarize:
Calling my WS from the browser it works.
Calling my WS using cURL it works.
Calling my WS using my callWsOldStyle() method it works.
Calling my WS using the method that use RestTemplate it go into error when my WS receive and try to handle the request.
So, what can be the cause of this issue? What am I missing? Maybe can depend by some wrong header or something like this?
As Pete said you are receiving an internal server error (status code 500) so you should check the server side of this rest service.
In any case you can do the following for the resttemplate
create an org.springframework.web.client.RequestCallback object if
you need to do something in the request
create an org.springframework.web.client.ResponseExtractor<String>
object in order to extract your data
use the resttemplate
org.springframework.web.client.RequestCallback
public class SampleRequestCallBack implements RequestCallback
{
#Override
public void doWithRequest(ClientHttpRequest request) throws IOException
{
}
}
org.springframework.web.client.ResponseExtractor
public class CustomResponseExtractor implements ResponseExtractor<String>
{
private static final Logger logger = LoggerFactory.getLogger(CustomResponseExtractor.class.getName());
#Override
public String extractData(ClientHttpResponse response) throws IOException
{
try
{
String result = org.apache.commons.io.IOUtils.toString(response.getBody(), Charset.forName("UTF8"));
if( logger.isInfoEnabled() )
{
logger.info("Response received.\nStatus code: {}\n Result: {}",response.getStatusCode().value(), result);
}
return result;
}
catch (Exception e)
{
throw new IOException(e);
}
}
}
REST TEMPLATE CALL
#Test
public void testStack()
{
try
{
String url = "http://5.249.148.180:8280/GLIS_Registration/6";
String response = restTemplate.execute(url, HttpMethod.GET, new SampleRequestCallBack(), new CustomResponseExtractor());;
logger.info(response);
}
catch (Exception e)
{
logger.error("Errore", e);
}
}
Angelo

unable to call a REST webservice..Full authentication required

I am currently working on spring application and REST webservices.
I have created a REST webservice in one application and want to access that service from other applications.
Below is the error its showing when trying to access the webservice.
RestClientException : org.springframework.web.client.HttpClientErrorException: 401 Full authentication is required to access this resource
Below is my webservice code:
#RequestMapping(value = MyRequestMapping.GET_ACC_DATA, method = RequestMethod.GET)
#ResponseBody
public MyResponseDTO getSigDataValues(#PathVariable final String acc, final HttpServletResponse response) throws Exception {
MyResponseDTO responseDTO = null;
try {
//logic goes here
//responseDTO = ..
} catch (Exception e) {
LOG.error("Exception" + e);
}
return responseDTO;
}
I am calling above webservice from another application.In the below mentioned method I am calling the webservice and its throwing me the exception org.springframework.web.client.HttpClientErrorException.
public MyResponseDTO getAccData(String acc){
try{
list= (List<String>)restTemplate.postForObject(MyDataURL.GET_ACC_DATA.value(), MyResponseDTO.class, acc);
}
catch (final RestClientException e)
{
LOG.info("RestClientException :" + e);
}
Please suggest, what am I missing.
You would need to authenticate against the REST service. One of the most common ways is Basic Authentication. If this is what the service is using you would need to create an AUTHORIZATION header with Base 64 encoded usernamen + password.
RestTemplate allow to set customer headers before the request gets sent.
The process of creating the Authorization header is relatively straightforward for Basic Authentication, so it can pretty much be done manually with a few lines of code:
private HttpHeaders createHeaders(String username, String password) {
return new HttpHeaders() {
private static final long serialVersionUID = -1704024310885506847L;
{
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")));
String authHeader = "Basic " + new String(encodedAuth);
set("Authorization", authHeader);
}
};
}
Then, sending a request becomes just as simple:
ResponseEntity<Dados> response = restTemplate.exchange(uriComponents.toUriString(), HttpMethod.GET,
new HttpEntity<Dados>(createHeaders(usuario, senha)), Dados.class);

spring : get response as Multipart File from REST WebService

I am creating POC for RESTFUL Web service using Spring 4.0. Requirement is to receive MultipartFile as Response from REST WEB-Service.
REST Service Controller
#RequestMapping(value="/getcontent/file", method=RequestMapping.post)
public MultipartFile getMultipartAsFileAsObject() {
File file = new File("src/test/resources/input.docx");
FileInputStream input = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile("file",file.getName(),
"application/docx", IOUtils.toByteArray(input));
return multipartFile
}
I call this service using third party Clients and Apache Http Client as well. kindly have a look on output.
Using Third party REST client ie. Postman
output looks like Json -
{
"name" : "file",
"originalfilename" : "sample.docx",
"contentType" : "application/docx",
"content" : [
82,
101,
97,
100,
101,
32,
32,
.
.
.
.
.
]
}
Apache HTTP Client Sample code
private static void executeClient() {
HttpClient client = new DefaultHttpClient();
HttpPost postReqeust = new HttpPost(SERVER_URI);
try{
// Set Various Attributes
HttpResponse response = client.execute(postReqeust) ;
//Verify response if any
if (response != null)
{
InputStream inputStream = response.getEntity().getContent();
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
OutputStream outputStream = new FileOutputStream
(new File("src/main/resource/sample.docx"));
outputStream.write(buffer);
outputStream.flush();
outputStream.close();
}
}
catch(Exception ex){
ex.printStackTrace();
}
Output of Apache Http client
file is getting Created but It is empty. (0 bytes).
I found some interesting answers from multiple stackoverflow questions.
Links are given below
file downloading in restful web services
what's the correct way to send a file from REST web service to client?
For Sending single file : (copied from above sources)
#GET
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile() {
File file = ... // Initialize this to the File path you want to serve.
return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"" ) //optional
.build();
}
For Sending Zip file : (copied from above sources)
1) Approach First :
You can use above method to send any file / Zip.
private static final String FILE_PATH = "d:\\Test2.zip";
#GET
#Path("/get")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile() {
File file = new File(FILE_PATH);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition", "attachment; filename=newfile.zip");
return response.build();
}
2) Approach Second :
#GET
#Path("/get")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public StreamingOutput helloWorldZip() throws Exception {
return new StreamingOutput(){
#Override
public void write(OutputStream arg0) throws IOException, WebApplicationException {
// TODO Auto-generated method stub
BufferedOutputStream bus = new BufferedOutputStream(arg0);
try {
Thread.currentThread().getContextClassLoader().getResource("");
File file = new File("d:\\Test1.zip");
FileInputStream fizip = new FileInputStream(file);
byte[] buffer2 = IOUtils.toByteArray(fizip);
bus.write(buffer2);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}

Resources