I have an EJB application which needs to send a XML object to a RESTfull service through HTTP Post. (All in the same infrastructure park)
I have seen some examples which the XML object is converted to String before send it to the service. However, I want to pass all the XML object itself. (I suppose it's possible)
For instance, in a web application architecture, I would do that by using RestTemplate, as follow:
RestTemplate restTemplate = new RestTemplate();
EmployeeVO result = restTemplate.postForObject( uri, newEmployee, EmployeeVO.class);
Now, I strictly should do the same using HttpURLConnection instead.
Someone can help me by showing some example?
The rest service only consumes "application/XML" and returns a String.
Follow my RESTfull signature and my XML object.
RESTFull Service
#RestController
#RequestMapping(value = "/analytic/")
public class AnalyticController {
#RequestMapping(value = "/requestProcessor", method = RequestMethod.POST, consumes = MediaType.APPLICATION_XML_VALUE)
public String analyticRequest(#RequestBody ServiceRequest serviceRequest){
//Some code here...
return "0";
}
}
Domain
#XmlRootElement(name = "ServiceRequest")
public class ServiceRequest implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#XmlAttribute(name = "Method")
private String method;
#XmlElement(name = "Credential")
private Credential credential;
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public Credential getCredential() {
return credential;
}
public void setCredential(Credential credential) {
this.credential = credential;
}
}
Thanks in advance.
Thank you all for your thoughts!
I could solve my issue by doing the below code.
URL url = new URL("http://server:port/service_path");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/xml");
OutputStream os = connection.getOutputStream();
JAXBContext jaxbContext = JAXBContext.newInstance(MyClass.class);
jaxbContext.createMarshaller().marshal(MyClass, os);
os.flush();
Related
I just made a new Springboot Project and every time I want so implement the Controller for the Mapping from my API into my Database I get the statuscode 302.
The class I want to put into the db is a Movie, here is the Moviecontroller
#RestController()
#RequestMapping(path = "movie")
public class MovieController {
private final MovieService movieService;
#Autowired
public MovieController(MovieService movieService){ this.movieService = movieService; }
#GetMapping("getmovie")
public List<Movie> getMovie(){
return movieService.getMovie();
}
#PostMapping(path = "postmovie")
public void addNewMovie(#RequestBody Movie movie){
movieService.addNewMovie(movie);
}
}
The Class which handles the API has this method in it which is supposed to handle a Movie Json and send it via http to the Controller. Since I want to post the minimum code necessary for this Problem I do not post the complete class. The Route is...
#Route(value = "addmovie", layout = MainLayout.class)
public void saveMovieInDatabase(int movieId, String title, String posterSrc, int releaseDate,int length) throws IOException {
String movieString = new ObjectMapper().writeValueAsString(new Movie(movieId,title,posterSrc,releaseDate,length));
CloseableHttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost("http://localhost:8080/movie/postmovie");
post.setEntity(new StringEntity(movieString));
post.setHeader("Accept","application/json");
post.setHeader("Content-type", "application/json");
CloseableHttpResponse response = client.execute(post);
System.out.println(response.getStatusLine().getStatusCode());
}
My issue is when I try this I get a media type error, then I changed the header. Now I receive a 500 error. The problem isnt the api , on postman it works perfectly , am I doing something wrong in my code when requesting a post?
My object model
public class EmailModel {
private String module;
private String notificationGroupType;
private String notificationGroupCode;
private String notificationType;
private String inLineRecipients;
private String eventCode;
private HashMap<String, Object> metaData;
public EmailModel() {
this.module = "CORE";
this.notificationGroupType = "PORTAL";
this.notificationGroupCode = "DEFAULT";
this.notificationType = "EMAIL";
this.inLineRecipients = "[chrispotjnr#gmail.com,chris#mqattach.com]";
this.eventCode = "DEFAULT";
this.metaData = metaData;
}
}
My Controller
It should send a post request with a object body, the emails get sent
#RequestMapping(value = "test", method = RequestMethod.Post)
public void post() throws Exception {
String uri = "TestUrl";
EmailModel em = new EmailModel();
EmailModel data = em;
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
.headers("Content-Type", "application/json")
.uri(URI.create(uri))
.POST(HttpRequest.BodyPublishers.ofString(String.valueOf(data)))
.build();
HttpResponse<?> response = client.send(request, HttpResponse.BodyHandlers.discarding());
System.out.println(em);
System.out.println(response.statusCode());
}
postmanImage
You must to convert EmailModel to json format by ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
String data = objectMapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(em);
and change POST to :
.POST(HttpRequest.BodyPublishers.ofString(data))
See more about ObjectMapper
Capture requests and cookies(on the left side of setting icon)
->Request
->port and put the port number there
Im new to Spring and im trying to understand it. Is it possible for me to use Spring boot to make calls to someone else's api? for example, the api im using needs to be authenticated using credentials they give me. I would like to use their API to make POST requests. So far I have found documents that relate to using your own API. These requests require headers to be passed as well.
Whats the simplest way I can do a POST request, passing my credentials and the required headers using Spring ?
Any help would be appreciated.
if i understand u well, u need to post another web-api with credentials okay you can use
restTemplate like the following example
public List<EtisAccount> getAllActiveAccount(){
logger.debug("Debug: in Class \t"+this.getClass().getName()+" Method Name is: \t"+new Object() {}.getClass().getEnclosingMethod().getName());
Properties sprinklrProp=sprinklrProperties.getSprinklrKeys();
SprinklrCredential sprinklrCredential=credentialBuilder.getSprinklrCredential();
RestTemplate restTemplate= new RestTemplate();
HttpHeaders header = new HttpHeaders();
header.setBearerAuth(sprinklrCredential.getAccess_token());
header.add("key", sprinklrCredential.getApi_key());
header.set("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);
UriComponentsBuilder uriBuilder= UriComponentsBuilder.fromUriString(sprinklrProp.getProperty("sprinlrUri").toString())
.queryParam("types", sprinklrProp.getProperty("accountTypes").toString());
HttpEntity<String> entity= new HttpEntity<>(header);
sslCertificateValidation.disable();
ResponseEntity<String> sprinklrResponse=restTemplate.exchange(uriBuilder.toUriString(),HttpMethod.GET,entity, String.class);
List<EtisAccount> activeAccouts=etisAccountHelper.getAllSocialEtisAccounts(sprinklrResponse.getBody());
logger.debug(String.valueOf(sprinklrResponse.getStatusCodeValue()));
logger.debug(activeAccouts.toString());
return activeAccouts;
}
this is sample example for call online-API using RestTemplate
here i build header with credentials (bearer authentication)
HttpHeaders header = new HttpHeaders();
header.setBearerAuth(sprinklrCredential.getAccess_token());
header.add("key", sprinklrCredential.getApi_key());
header.set("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);
and here i add header requestEntity to add to resttemplate request
HttpEntity<String> entity= new HttpEntity<>(header);
and here i get response using exchange method
ResponseEntity<String> sprinklrResponse=restTemplate.exchange(uriBuilder.toUriString(),HttpMethod.POST,entity, String.class);
You need following things :
Create a Spring web starter project from https://start.spring.io/
Create a new Java Class in your project and name it Controller. Add #RestController annotation to on class level.
Configure RestTemplate object in SpringBootApplication
Autowire that RestTemplate object in Controller class
Create a method in Controller class which using RestTemplate, will call the #PostMapping to their API.
You can try this way
This is the simple way to this
You can set user name and password as basic Auth
public class RESTInvoker {
private final String baseUrl;
private final String username;
private final String password;
public RESTInvoker(String baseUrl, String username, String password) {
this.baseUrl = baseUrl;
this.username = username;
this.password = password;
}
String getDataFromServer(String path) {
StringBuilder sb = new StringBuilder();
try {
URL url = new URL(baseUrl + path);
URLConnection urlConnection = setUsernamePassword(url);
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.close();
return sb.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private URLConnection setUsernamePassword(URL url) throws IOException {
URLConnection urlConnection = url.openConnection();
String authString = username + ":" + password;
String authStringEnc = new String(Base64.encodeBase64(authString.getBytes()));
urlConnection.setRequestProperty("Authorization", "Basic " + authStringEnc);
return urlConnection;
}
}
I have several servlets, which
take JSON-encoded requests as inputs,
process them and
return responses to the client as JSON-encoded objects.
Up to now I used Android as client (sample Android code see below).
Now I want to write a plain old Java program, which would send requests and receive the responses (do the same as the Android code). For this purpose I wrote a Java test (code see below, section Java code) and ran it.
At the client side I get this error:
21:43:38.930 [main] ERROR r.a.c.t.TestAcceptanceProcedure1 -
java.io.IOException: Server returned HTTP response code: 405 for URL: http://myserver/myapp/rest/GetUserIdService
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441) ~[na:1.6.0_23]
at testclient.TestAcceptanceProcedure1.test(TestAcceptanceProcedure1.java:47) ~[test-classes/:na]
In the server log, I see this message:
WARNING: No operation matching request path "/myapp/rest/GetUserIdService" is found, Relative Path: /, HTTP Method: GET, ContentType: */*, Accept: text/html,image/gif,image/jpeg,*/*,*/*;q=.2,. Please enable FINE/TRACE log level for more details
Question: How should I change my Java test to fix this error?
Note that the server is up and running (when I execute the Android code, it works).
Android code:
Sending the request and receiving the response:
final GetSimulationStatusRequest request = new GetSimulationStatusRequest();
final String json = Utils.convertToJson(request, getClass());
final String serverUrl = Utils.getServerUrl(this, "GetSimulationStatusService");
final IGetSimulationStatusAsyncTask getSimulationStatusTask =
asyncTaskFactory.createGetSimulationStatusAsyncTask(getWebServiceHelper());
Utils.setRequestAndServerUrl(json, serverUrl, getSimulationStatusTask);
final GetSimulationStatusResponse simulationStatusReponse =
getSimulationStatusTask.get();
Utils.convertToJson:
public static String convertToJson(final Object aRequest, Class<? extends Activity> aClass) {
final ObjectMapper mapper = new ObjectMapper();
String json = null;
try {
json = mapper.writeValueAsString(aRequest);
} catch (final JsonProcessingException exception) {
Log.e(aClass.getSimpleName(), exception.getLocalizedMessage(),
exception);
}
return json;
}
Utils.setRequestAndServerUrl:
public static void setRequestAndServerUrl(final String aJson,
final String aServerUrl, final IAsyncTask aTask) {
aTask.addNameValuePair("request", aJson);
aTask.sendRequest(new String[] { aServerUrl });
}
GetSimulationStatusAsyncTask:
public class GetSimulationStatusAsyncTask
extends AsyncTask<String, String, GetSimulationStatusResponse>
implements IGetSimulationStatusAsyncTask {
private static final String TAG = GetSimulationStatusAsyncTask.class.getSimpleName();
private IWebServiceTaskHelper helper;
private ICcpResponseParser<GetSimulationStatusResponse> responseParser =
new CcpResponseParser<GetSimulationStatusResponse>();
public GetSimulationStatusAsyncTask(final IWebServiceTaskHelper aHelper) {
helper = aHelper;
}
#Override
public void addNameValuePair(final String aName, final String aValue) {
helper.addNameValuePair(aName, aValue);
}
#Override
protected GetSimulationStatusResponse doInBackground(String... aArgs) {
return (GetSimulationStatusResponse)Utils.processResponse(this.helper, TAG, responseParser,
GetSimulationStatusResponse.class, aArgs);
}
#Override
public void sendRequest(final String[] aArgs) {
execute(aArgs);
}
}
Java code:
#Test
public void test() throws JsonProcessingException, MalformedURLException {
final GetUserIdRequest request = new GetUserIdRequest();
request.setDeviceId("PC1");
final String requestAsString = convertToJson(request);
final String serverUrl = getServerUrl("GetUserIdService");
final URL url = new URL(serverUrl);
HttpURLConnection connection = null;
InputStream inputStream = null;
try {
connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("request", requestAsString);
connection.connect();
inputStream = connection.getInputStream();
final String responseAsString = IOUtils.toString(inputStream);
LOGGER.debug("responseAsString: " + responseAsString);
} catch (final IOException exception) {
LOGGER.error("", exception);
}
finally
{
IOUtils.closeQuietly(inputStream);
}
}
private String convertToJson(final GetUserIdRequest aRequest) throws JsonProcessingException {
final ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(aRequest);
}
private String getServerUrl(final String aServiceName)
{
return "http://myserver.com/myapp/rest/" + aServiceName;
}
Update 1 (09.10.2013 12:23 MSK):
#Path("/GetSimulationStatusService")
public class GetSimulationStatusService extends BaseCcpService {
private GetSimulationStatusRequestParser requestParser =
new GetSimulationStatusRequestParser();
#POST
#Produces("text/plain")
public String getSimulationStatus(#FormParam("request") final String aRequestJson)
throws JsonProcessingException
{
final GetSimulationStatusRequest request = requestParser.convert(aRequestJson);
final GetSimulationStatusResponse response = new GetSimulationStatusResponse();
response.setRequestId(request.getId());
response.setCycle(getPersistence().getCurrentCycle(request.getUserId()));
response.setLabourForce(getPersistence().getLabourForceSimulationParameter(
request.getUserId()));
return getObjectMapper().writeValueAsString(response);
}
}
Update 2 (09.10.2013 20:48 MSK): When I change the code like shown below, I get 500 HTTP response. At the server side, the aRequest argument of the method GetUserIdService.getUserId is null.
connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("request", requestAsString);
connection.setRequestMethod("POST"); // Added this line
connection.connect();
Update 3 (09.10.2013 23:15): This one works:
#Test
public void test() throws JsonProcessingException, MalformedURLException
{
final GetUserIdRequest request = new GetUserIdRequest();
request.setDeviceId("PC1");
final String requestAsString = convertToJson(request);
final String serverUrl = getServerUrl("GetUserIdService");
final URL url = new URL(serverUrl);
HttpURLConnection connection = null;
InputStream inputStream = null;
OutputStream outputStream = null;
try {
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.connect();
outputStream = connection.getOutputStream();
IOUtils.write("request=" + requestAsString, outputStream);
inputStream = connection.getInputStream();
final String responseAsString = IOUtils.toString(inputStream);
LOGGER.debug("responseAsString: " + responseAsString);
} catch (final IOException exception) {
LOGGER.error("", exception);
}
finally
{
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
}
}
The 405 HTTP error code means that given method (GET) is not supported by the endpoint. Probably instead of GET request you want to send POST. I don't know what kind of request is sent by Android client.
Do you have endpoint specification/documentation?
Here you'll find information how to invoke POST using plain Java API. If you can use external libraries in your test then it can be achieved a lot easier using RESTEasy.
I want to use #Produces({Mediatype.Application_XML , Mediatype.Application_JSON}) in a program that I am writing. I want to use this on only one method, but I am confused that when will it return a JSON object and when will it return an XML page. Here is the code I am writing and in both the cases it returns me an XML feed. I want it to return an JSON object if it does not meet the if-else criterion.
#Path("/{search}")
#GET
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public String getCountryData(#PathParam("search") String search, #QueryParam("ccode") String ccode , #QueryParam("scode") String scode) {
if(ccode.equals("XML")){
return "<note> <to>Tove</to> <from>Jani</from><heading>Reminder</heading> <body>Don't forget me this weekend!</body></note>";
}
return EndecaConn.ConnectDB("Search", search,"mode matchallpartial" );
}
The media type will be part of the request, you shouldn't include it as a query parameter. Below is some sample Java code that would request the data as application/xml.
String uri =
"http://localhost:8080/CustomerService/rest/customers/1";
URL url = new URL(uri);
HttpURLConnection connection =
(HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/xml");
JAXBContext jc = JAXBContext.newInstance(Customer.class);
InputStream xml = connection.getInputStream();
Customer customer =
(Customer) jc.createUnmarshaller().unmarshal(xml);
connection.disconnect();
In your example you could have different methods corresponding to the same path for the different media types.
#Path("/{search}")
#GET
#Produces(MediaType.APPLICATION_JSON)
public String getCountryDataJSON(#PathParam("search") String search, #QueryParam("scode") String scode) {
return JSON;
}
#Path("/{search}")
#GET
#Produces(MediaType.APPLICATION_XML)
public String getCountryDataXML(#PathParam("search") String search, #QueryParam("scode") String scode) {
return XML;
}
You have to return a Response object with the entity set to your domain entity. The serialization of the xml/json is done automatically.
See: https://jsr311.java.net/nonav/releases/1.1/javax/ws/rs/core/Response.html
yYou can return an entity like this:
Foo myReturn = new Foo(blah,blah,blah)
return Response.ok(myReturn).build()
If you need fine grained serialization you can use annotations on your domain class.