I am new to Restful web service in java and this is my first web application, I searched a lot but everybody asking more complicated question than what I need.
I have a pretty simple html with a textbox and a submit button. Also I have a POST function in my web service as below:
#POST
#Consumes({MediaType.APPLICATION_FORM_URLENCODED,MediaType.APPLICATION_JSON})
public Response showSearchResult(String incomingData) throws Exception {
String query = incomingData;
RepositoryMongo repository = new RepositoryMongo("InvertedIndex", "InvertedIndex", "documents");
InvertedIndex invertedIndex = new InvertedIndex(repository);
ArrayList<Posting> result = invertedIndex.processQuery_Posting_Based(query, 10,"1");
String htmlResult = invertedIndex.getHTMLResult(result);
return Response.ok(htmlResult).build();
}
The problem is that my incomingData = "query_input=canada+singer&search=search", while I want it to be the content of the textbox only. I can parse the string that I am receiving, but is that way correct? Is there any way that I can get "canada singer" as input directly? how can I control input type?
You can use the #FormParam annotation for a POST request, or the #PathParam annotation for a GET request. These go on parameters to your method, to indicate that the values for the parameters should be pulled out of either the URL (for a GET) or the posted body (for a POST).
Have a look at section 7.3 of http://www.vogella.com/tutorials/REST/article.html where there is a working example.
For this result - “query_input=canada+singer" ,you can get the url value with #QueryParam("query_input").
Alternatively,
We can even implement this using this #Context UriInfo
getQueryParameters() method has getFirst - in which you include the argument to fetch,just like below
String query_input_value= url.getQueryParameters().getFirst("query_input");
Try this :
#POST
#Consumes({MediaType.APPLICATION_FORM_URLENCODED,MediaType.APPLICATION_JSON})
public Response showSearchResult(#Context UriInfo url) throws Exception {
String query_input_value= url.getQueryParameters().getFirst("query_input");
String query = incomingData;
RepositoryMongo repository = new RepositoryMongo("InvertedIndex", "InvertedIndex", "documents");
InvertedIndex invertedIndex = new InvertedIndex(repository);
ArrayList<Posting> result = invertedIndex.processQuery_Posting_Based(query, 10,"1");
String htmlResult = invertedIndex.getHTMLResult(result);
return Response.ok(htmlResult).build();
}
Related
I have been trying to use restful webservice in place of legacy soap webservice without altering the user part of the request. I wanted to know whether this is achievable. Here is a sample code to demonstrate the issue :
Soap request :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sch="https://www.flopradalley.com/xml/school">
<soapenv:Header/>
<soapenv:Body>
<sch:StudentDetailsRequest>
<sch:name>Arun</sch:name>
</sch:StudentDetailsRequest>
</soapenv:Body>
</soapenv:Envelope>
And this is my rest controller which should be able to respond to the request from SoapUI :
#RestController
#RequestMapping(value = "/restservice")
public class KenRestController {
#RequestMapping(value = "/details", method = RequestMethod.POST,
produces = MediaType.TEXT_XML_VALUE, consumes = MediaType.TEXT_XML_VALUE
)
public StudentDetailsResponse execute(HttpServletRequest request)
{
StudentDetailsRequest objectFromBody = null;// unmarshall the object from soap request and store it here
StringBuffer sb = new StringBuffer();
try {
BufferedReader reader = request.getReader();
String lineStr = null;
while ((lineStr = reader.readLine()) != null) {
sb.append(lineStr);
}catch(IOException ex) {
ex.printStackTrace();
}
/* other code */
return ---;
}
}
I was only able to get the soap request as text and store it in a string buffer. I know this isn't remotely the way it should be done if it is possible to handle soap requests using rest. I know that rest is an archicture and is a whole lot difference from soap and it looks like there is no direct way to handle soap requests using rest at the least.
Apart from this sample code, I should be able to extract the SoapMessage, MessageContext, Soapheader, SoapBody from the request. That brings me to the original question on whether it is possible?
If you make the change into a REST API I highly recommend to not keep thinging in some of the webservice logic.
The SOAP protocol is a method to pass information that contains both the answer and the metadata of the call.
In rest you obtain the answer in the body of the responses and the most used format is json. You can directly pass as a parameter in the method the object that is going to be parsed into the java object by Spring REST (it uses Jackson library to parse in reality).
#RestController
public class KenRestController {
#GetMapping("/restService/details/{studentId}") // post is for saving an elelement
public StudentDetailsResponse getDetails(#PathVariable("studentId") Integer studentId) {
// you get the details and parse it to the object you want to return
return studentService.getStudentById(studentId);
}
// example of response class
private class StudentDetailsResponse implements Serializable{
// pojo class
}
}
Please don't hesitate to make any questions about that.
I am trying to access the contents of an API and I need to send a URL using RestTemplate.
String url1 = "http://api.example.com/Search?key=52ddafbe3ee659bad97fcce7c53592916a6bfd73&term=&limit=100&sort={\"price\":\"desc\"}";
OutputPage page = restTemplate.getForObject(url1, OutputPage .class);
But, I am getting the following error.
Exception in thread "main" java.lang.IllegalArgumentException: Not enough variable values available to expand '"price"'
at org.springframework.web.util.UriComponents$VarArgsTemplateVariables.getValue(UriComponents.java:284)
at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:220)
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:317)
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:46)
at org.springframework.web.util.UriComponents.expand(UriComponents.java:162)
at org.springframework.web.util.UriTemplate.expand(UriTemplate.java:119)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:501)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:239)
at hello.Application.main(Application.java:26)
If I remove the sort criteria, it is working properly.
I need to parse the JSON using sort criteria.
Any help will be much appreciated.
Thanks
The root cause is that RestTemplate considers curly braces {...} in the given URL as a placeholder for URI variables and tries to replace them based on their name. For example
{pageSize}
would try to get a URI variable called pageSize. These URI variables are specified with some of the other overloaded getForObject methods. You haven't provided any, but your URL expects one, so the method throws an exception.
One solution is to make a String object containing the value
String sort = "{\"price\":\"desc\"}";
and provide a real URI variable in your URL
String url1 = "http://api.example.com/Search?key=52ddafbe3ee659bad97fcce7c53592916a6bfd73&term=&limit=100&sort={sort}";
You would call your getForObject() like so
OutputPage page = restTemplate.getForObject(url1, OutputPage.class, sort);
I strongly suggest you do not send any JSON in a request parameter of a GET request but rather send it in the body of a POST request.
If the solution suggested by sotirios-delimanolis is a little difficult to implement in a scenario, and if the URI string containing curly braces and other characters is guaranteed to be correct, it might be simpler to pass the encoded URI string to a method of RestTemplate that hits the ReST server.
The URI string can be built using UriComponentsBuilder.build(), encoded using UriComponents.encode(), and sent using RestTemplate.exchange() like this:
public ResponseEntity<Object> requestRestServer()
{
HttpEntity<?> entity = new HttpEntity<>(requestHeaders);
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(rawValidUrl)
.queryParams(
(LinkedMultiValueMap<String, String>) allRequestParams);
UriComponents uriComponents = builder.build().encode();
ResponseEntity<Object> responseEntity = restTemplate.exchange(uriComponents.toUri(), HttpMethod.GET,
entity, String.class);
return responseEntity;
}
Building, encoding, and extracting URI have been seperated out for clarity in the above code snippet.
You can URL encode the parameter values:
String url1 = "http://api.example.com/Search?key=52ddafbe3ee659bad97fcce7c53592916a6bfd73&term=&limit=100&sort=";
org.apache.commons.codec.net.URLCodec codec = new org.apache.commons.codec.net.URLCodec();
url1 = url1 + codec.encode("{\"price\":\"desc\"}");
OutputPage page = restTemplate.getForObject(url1, OutputPage.class);
You can set a specific UriTemplateHandler in your restTemplate. This handler would just ignore uriVariables :
UriTemplateHandler skipVariablePlaceHolderUriTemplateHandler = new UriTemplateHandler() {
#Override
public URI expand(String uriTemplate, Object... uriVariables) {
return retrieveURI(uriTemplate);
}
#Override
public URI expand(String uriTemplate, Map<String, ?> uriVariables) {
return retrieveURI(uriTemplate);
}
private URI retrieveURI(String uriTemplate) {
return UriComponentsBuilder.fromUriString(uriTemplate).build().toUri();
}
};
restTemplate.setUriTemplateHandler(skipVariablePlaceHolderUriTemplateHandler);
You can encode url before using RestTemplate
URLEncoder.encode(data, StandardCharsets.UTF_8.toString());
You can simply append a variable key to the URL and give the value using the restTemplate.getForObject() method.
Example:
String url = "http://example.com/api?key=12345&sort={data}";
String data="{\"price\":\"desc\"}";
OutputPage page = restTemplate.getForObject(url, OutputPage.class, data);
I am trying to consume the following HTTPS endpoints from Yahoo Weather Service:
Yahoo Weather Service API
I am doing some special query according to the API to get the current weather at some parametrized location.
#Service("weatherConditionService")
public class WeatherConditionServiceImpl implements WeatherConditionService {
private static final String URL = "http://query.yahooapis.com/v1/public/yql";
public WeatherCondition getCurrentWeatherConditionsFor(Location location) {
RestTemplate restTemplate = new RestTemplate();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(URL);
stringBuilder.append("?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22");
// TODO: Validate YQL query injection
stringBuilder.append(location.getName());
stringBuilder.append("%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys");
WeatherQuery weatherQuery = restTemplate.getForObject(stringBuilder.toString(), WeatherQuery.class);
// TODO: Test Json mapping response
Condition condition = weatherQuery.getQuery().getResults().getChannel().getItem().getCondition();
return new WeatherCondition(condition.getDate(), Integer.parseInt(condition.getTemp()), condition.getText());
}
Location is a class that provides the attribute "name" that is a String description of the location, such as "New York" or "Manila".
Condition an other classes just map the returning object.
When executing I get the following HTTP response:
org.springframework.web.client.HttpClientErrorException: 403 Forbidden
So this means I am not authorized to access the resource from what I understand.
The URL works great if I just copy & paste it in a web browser:
Yahoo Weather Query
I think that mapping is not a problem since I am not getting "400" (Bad Request) but "403" (Forbidden)
There must be some error on the way I use the RestTemplate object. I am researching but I can't find an answer.
The docs say you need an api key. But when I make a call like this:
fetch('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22nome%2C%20ak%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys')
.then(resp=> resp.json())
.then((res)=>console.log(res.query.results))
https://repl.it/NeoM
It works fine without one. Perhaps you've been blackisted for hitting the api too often.
Your code seems fine.
I finally found the answer. It finally WAS a Bad Request because I needed to pass the parameters differently (not as part of the URL).
I found the answer here. Here goes the code for my particular Yahoo Weather API call return a String (I still will have to do some work to use the mapping).
private static final String URL = "http://query.yahooapis.com/v1/public/yql";
public String callYahooWeatherApi() {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(URL)
.queryParam("q", "select wind from weather.forecast where woeid=2460286")
.queryParam("format", "json");
HttpEntity<?> entity = new HttpEntity<>(headers);
HttpEntity<String> response = restTemplate.exchange(
builder.build().encode().toUri(),
HttpMethod.GET,
entity,
String.class);
return response.getBody();
}
I need to implement robospice for doing the networking part in my Translator app. I previously used async task class and it was working fine, but now i want to improve my application with implementing robospice. I'am trying to execute the following code but it doesn't't throw any exception it just never executes....
#Override
public TranslatedText loadDataFromNetwork() throws Exception {
String jsonString = getJsonString();
String headerValue = getHeaderValue(jsonString);
String text = pair.getWordPairs().getWordFrom();
String languageFrom = pair.getLanguagePairs().getLanguageFrom().getCode();
String languageTo = pair.getLanguagePairs().getLangougateTo().getCode();
String uri = String
.format("http://api.microsofttranslator.com/v2/Http.svc/Translate?text=%s&from=%s&to=%s&contentType=text/html",
URLEncoder.encode(text, "UTF-8"),
URLEncoder.encode(languageFrom, "UTF-8"),
URLEncoder.encode(languageTo, "UTF-8"));
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", headerValue);
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
// Add the Simple XML message converter
getRestTemplate().getMessageConverters().add(new SimpleXmlHttpMessageConverter());
//set the headerValue in the Entity
org.springframework.http.HttpEntity<?> request = new org.springframework.http.HttpEntity<Object>(headerValue);
// Make the HTTP GET request, marshaling the response from XML to an
// EventList
Log.v("request","Making request!");
//This line never finish execuitng, doesen't throw exception or anything in logCat
ResponseEntity<Object> responseEntity = getRestTemplate().exchange(uri, HttpMethod.GET, request, null);
Log.v("request", responseEntity.getBody().toString());
Log.d("Load Data From Network", request.getBody().toString());
return null;
}
The last thing it shows in log cat is Request First!! And nothing after that. It never even gets to The Request Listener onRequestFailure.
Can any 1 tell me what i do wrong ?
This is what look weird to me in your code:
ResponseEntity<Object> and null as 4th parameter of the exchange method are not correct. You need to provide a type which represents the response you get from the server.
The object returned by loadDataFromNetwork() is what you will get in the onRequestSuccess() method. Returning null is not a good idea, in my opinion.
I fixed the problem. So if you need to handle stream you will have to provide the following code
ResponseEntity<byte[]> responseEntity = getRestTemplate().exchange(uri, HttpMethod.GET, request, byte[]);
I need to retrieve URL from current Web page opened in Firefox by using Wicket. Can somebody tell me how to do that?
To get the current page's url use the webrequest and UrlRenderer:
Url url = ((WebRequest)RequestCycle.get().getRequest()).getUrl();
String fullUrl = RequestCycle.get().getUrlRenderer().renderFullUrl(url);
You need to query the underlying HTTPServletRequest:
public class DummyPage extends WebPage{
private String getRequestUrl(){
// this is a wicket-specific request interface
final Request request = getRequest();
if(request instanceof WebRequest){
final WebRequest wr = (WebRequest) request;
// but this is the real thing
final HttpServletRequest hsr = wr.getHttpServletRequest();
String reqUrl = hsr.getRequestURL().toString();
final String queryString = hsr.getQueryString();
if(queryString != null){
reqUrl += "?" + queryString;
}
return reqUrl;
}
return null;
}
}
Reference:
(Wicket) Component.getRequest()
(Wicket) Request
(Wicket) WebRequest
(Servlet API) HTTPServletRequest
The solution from Sean Patrick Floyd seems to be obsolete for wicket 1.5
If using wicket 1.5 (or above I guess) here is the solution:
RequestCycle.get().getUrlRenderer().renderFullUrl(
Url.parse(urlFor(MyPage.class,null).toString()));
Reference:
Getting a url for display
Depending on what exactly you want, this may not be possible. There is a short guide here in the Wicket wiki, but it has some caveats, notably that it only returns a relative URL in versions of Wicket after 1.3. That said, the method used is
String url = urlFor("pageMapName", MyPage.class, new PageParameters("foo=bar"));
If you go with the wiki's alternate method — the one involving the form — be warned: getPage() is not part of Wicket's public API.
This works. I'm using wicket 1.5;
new URL(RequestCycle.get().getUrlRenderer().renderFullUrl(
Url.parse(urlFor(HomePage.class,null).toString()))).getAuthority();
Example: http://example.com:80/a_long_path/
getAuthproty() will return example.com:80
getHost() will return example.com.