Using POST in Rest API just like get to add 2 numbers - rest

I am new to REST and web services. I am trying to add two numbers with the below code.
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/calc")
public class CalcREST {
/*#GET
#Path("/add/{a}/{b}")
#Produces(MediaType.TEXT_PLAIN)
public String addPlainTextPost(#PathParam("a") double a, #PathParam("b") double b) {
return (a + b) + "";
}*/
#POST
#Path("/add/{a}/{b}")
#Produces(MediaType.TEXT_PLAIN)
public String addPlainTextPost(#PathParam("a") double a, #PathParam("b") double b) {
return addPlainText(a,b);
}
public String addPlainText(double a, double b) {
return (a + b) + "";
}
}
I am trying to test using both GET and POST. For both GET and POST I am invoking the APIs as
http://:9999/calcrest/calc/add/1/5
For Get I get the results properly. However If i comment out GET and keep POST, I am not able to get any results, just blank.
Any help would be appreciated.

I am assuming that you are calling this url from a browser and a browser is always going to do a GET on the url. If you want to try POST, you will have to either write a REST client in any one of your preferred languages (javascript, java) or if you are using firefox you can use POSTER plugin to simulate a POST. See here: POSTER.
Here is a quick REST client example (code snippet) in java. I have used jersey REST client.
WebResource webResource = restClient.resource("/calcrest/calc/add");
webResource = webResource.path("1").path("5");
String response = webResource.type(MediaType.TEXT_PLAIN)
.accept(MediaType.TEXT_PLAIN)
.post(ClientResponse.class);
System.out.println("Your addition: "+response);
I hope this helps!

Related

Citrus framework: How to make a soap response / citrus variable / citrus function return result available to java

I'm using Citrus 2.7.8 with Cucumber 2.4.0. I'm making a soap call and want to get the response and do some advanced parsing on it to validate a graphql response has matching values. (I understand how to do validations when it's something that just has one element, but I need something able to handle when there could be one or many elements returned (for example, 1 vehicle or 4 vehicles)). To make my validation very dynamic and able to handle many different 'quotes', I want to store the response to a Citrus variable and then make it available to java to read in the file and do the advanced parsing and validation.
The TestContext injection doesn't appear to currently work with cucumber (see https://github.com/citrusframework/citrus/issues/657) so I'm using the workaround here:
How to inject TestContext using TestRunner and cucumber to manually create the context. Without this I get a nullpointerexception on anything with the context.
I am able to use Citrus's message function to grab the soap response which is awesome. My echo statements in the console show that it successfully put the right value into the citrus variable. But I'm having problems making that available to java so that I can then open it up and parse through it.
I've scaled down my step definition file to just the pertinent code. My couple attempts are listed below along with the problems I encountered in their results.
Does anyone have any ideas on how I can successfully workaround the context issues and make my response available to java?
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import com.consol.citrus.Citrus;
import com.consol.citrus.annotations.CitrusFramework;
import com.consol.citrus.annotations.CitrusResource;
import com.consol.citrus.config.CitrusSpringConfig;
import com.consol.citrus.context.TestContext;
import com.consol.citrus.dsl.junit.JUnit4CitrusTestRunner;
import com.consol.citrus.dsl.runner.TestRunner;
import com.consol.citrus.ws.client.WebServiceClient;
import cucumber.api.java.en.When;
#ContextConfiguration(classes = CitrusSpringConfig.class)
public class CitrusSteps extends JUnit4CitrusTestRunner {
#CitrusFramework
private Citrus citrus;
#CitrusResource
private TestRunner runner;
#CitrusResource
private TestContext context;
#Autowired
private WebServiceClient getQuote;
#When("^I call getQuote with id \"([^\"]*)\"$")
public void i_call_getquote_with_id(String quoteId) throws Throwable {
context = citrus.createTestContext();
String soappayload = "my payload (taken out for privacy purposes)";
runner.soap(action -> action.client(getQuote)
.send()
.soapAction("getQuote")
.payload(soappayload));
runner.soap(action -> action.client(getQuote)
.receive()
.name("getQuoteResponseStoredMessage"));
//this bombs out on the context line with this: "com.consol.citrus.exceptions.CitrusRuntimeException: Unknown variable 'messageStoreGetQuoteResponse1'"
runner.variable("messageStoreGetQuoteResponse1", "citrus:message(getQuoteResponseStoredMessage.payload())");
runner.echo("First try: ${messageStoreGetQuoteResponse1}");
String firstTry = context.getVariable("messageStoreGetQuoteResponse1");
log.info("First Try java variable: " + firstTry);
//this bombs out on the context line with this: "com.consol.citrus.exceptions.CitrusRuntimeException: Unknown variable 'messageStoreGetQuoteResponse2'"
runner.createVariable("messageStoreGetQuoteResponse2", "citrus:message(getQuoteResponseStoredMessage.payload())");
runner.echo("Second try: ${messageStoreGetQuoteResponse2}");
String secondTry = context.getVariable("messageStoreGetQuoteResponse2");
log.info("Second Try java variable: " + secondTry);
//This stores the literal as the value - it doesn't store the message so it appears I can't use citrus functions within the context
context.setVariable("messageStoreGetQuoteResponse3", "citrus:message(getQuoteResponseStoredMessage.payload())");
String thirdTry = context.getVariable("messageStoreGetQuoteResponse3");
log.info("Third Try java variable: " + thirdTry);
}
}
A smart co-worker figured out a workaround for the injection not working w/ cucumber.
I replaced these two lines:
#CitrusResource
private TestContext context;
with these lines instead:
TestContext testContext;
public TestContext getTestContext() {
if (testContext == null) {
runner.run(new AbstractTestAction() {
#Override
public void doExecute(TestContext context) {
testContext = context;
}
});
}
return testContext;
}
Then within my step where I want the context, I can use the above method. In my case I wanted my message response, so I was able to use this and confirm that the response is now in my java variable:
String responseXML = getTestContext().getMessageStore().getMessage("getQuoteResponseStoredMessage").getPayload(String.class);
log.info("Show response XML: " + responseXML);

AEM - How to return page information in JSON format

I need to display the title and name of all child and grand child pages from given path in JSON format. Please provide the implementation.
First You have to try something yourself, then you call for help, not the complete solution!anyway there are couple of solution down there.
According to Adobe here you can implement page information in JSON format:
package com.adobe.example;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.Reference;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageInfoProvider;
#Component(metatype = false)
#Properties({
#Property(name="service.description", value="Returns the public URL of a resource.")
})
#Service
public class PageUrlInfoProvider implements PageInfoProvider {
#Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY)
private com.day.cq.commons.Externalizer externalizer;
private String fetchExternalUrl(ResourceResolver rr, String path) {
return externalizer.publishLink(rr, path);
}
public void updatePageInfo(SlingHttpServletRequest request, JSONObject info, Resource resource)
throws JSONException {
Page page = resource.adaptTo(Page.class);
JSONObject urlinfo = new JSONObject();
urlinfo.put("publishURL", fetchExternalUrl(null,page.getPath()));
info.put("URLs",urlinfo);
}
}
Or you may try this Page for solution
Please refer to below link which may be useful:
http://www.nateyolles.com/blog/2015/12/converting-aem-sling-resources-to-json.
Apart from the above solution you also use recursive level to get the data in the JSON format for example /content/we-retail/language-masters/en.{placeholder}.json
replace the placeholder with the level of nodes you want to print and return back the JSON wherever needed.
To know more about the rendering data in different formats,
Refer: https://sling.apache.org/documentation/bundles/rendering-content-default-get-servlets.html

How do I configure Zuul routing for URL with Token?

I am working with a microservice architecture where a Zuul gateway contacts a Eureka server to discover published microservices. I want my zuul gateway to accept path in a particular format.
It received a URL call with a member id sent as a token. Because we want to avoid sending sensitive information in URLs, these expirable tokens would be parsed by Zuul, translated to a Social Security Number, for example, and the ssn would be sent in a header.
For example, a bank acct GET:
http://zuulgateway/member/11/account/
would map to
http://microservice/account
X-MEMBER-SSN: 1112223333
My plan is to set up a "pre" Zuul filter to parse out the member token "11" and use it to get the SSN, then add it to the header.
But I'm not sure how I configure this route or if it is even possible.
zuul.routes.account.path: /member/*/**
does not achieve it. Is there some other mechanism I can use?
There are a few forum posts on the Zuul github regarding this issue but none of the solutions were working for me. I couldn't figure out why and finally realized: the hot deployment into Zuul from my Spring Tool Suite was restarting the application, but not deploying the latest changes (perhaps this is an endorsement for JRebel in the end!). Once I realized this I started experimenting with stop/deploy/start coding until I got a solution working with ZuulFilter.
The solution involves a "pre" filter which rewrites the contextURL to remove the /member/\d+/ portion of the URL so that the context can be directly mapped to the
Here is some example code:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
#Component
public class SpecialFilter extends ZuulFilter {
private static final String REQUEST_URI_KEY = "requestURI";
private static final Pattern URL_PATTERN = Pattern.compile("^\\/?(\\d+)\\/(.+)$");
#Override
public boolean shouldFilter() {
return isMember(RequestContext.getCurrentContext());
}
private boolean isMember(RequestContext currentContext) {
String path = (String) currentContext.get(REQUEST_URI_KEY);
Matcher m = URL_PATTERN.matcher(path);
return m.matches();
}
#Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
String originalRequestPath = (String) context.get(REQUEST_URI_KEY);
Matcher m = URL_PATTERN.matcher(originalRequestPath);
System.out.println("Parsing original "+originalRequestPath + " against " + URL_PATTERN.toString());
if(!m.matches()) {
System.err.println("Invalid URL");
return null;
}
String ssn = translateSSN(m.group(1));
String requestPath = m.group(2);
String modifiedRequestPath = "/" + requestPath;
context.put(REQUEST_URI_KEY, modifiedRequestPath);
//Add this header to the request
context.addZuulRequestHeader("X-SSN", ssn);
return null;
}
#Override
public String filterType() {
return "pre";
}
#Override
public int filterOrder() {
// Should proceed this filter
return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
}
}

CQ5 - displaying a CQ.Notification in the frontend, when a workflow finished

I implemented workflows, but it would be nice to know if there are hooks provided by the client library which allow to hook in. When a workflow was triggered and finished, a CQ.Notification should be displayed. Or do i need to implement a polling library by myself?
As far as I know, there is no built-in CQ area to see when something is done, aside from looking here:
http://yoursite.com:port/libs/cq/workflow/content/console.html
Once there, you can go to the 'Instances' tab and see what's happening.
In one application that I worked on, we ended up writing our own method that sends notifications to us based on one of our workflows (our workflow ties into it - from the workflow models area, you can set your process to be a servlet that you've put into CQ). Here is the main piece of code from our servlet that catches the process being active, and then calls our methods to email us based on what it finds:
import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.exec.WorkflowData;
import com.day.cq.workflow.exec.WorkflowProcess;
import com.day.cq.workflow.metadata.MetaDataMap;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import java.util.Arrays;
public class YourServletName implements WorkflowProcess {
#Override
public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap args) throws WorkflowException {
session = workflowSession.getSession();
final WorkflowData data = workItem.getWorkflowData();
String type = data.getPayloadType();
String[] argStrings = args.get("PROCESS_ARGS", ARG_UPDATED).split(",");
String reason = argStrings[0];
String baseUrl = argStrings[1];
try {
if (type.equals(TYPE_JCR_PATH) && data.getPayload() != null) {
String resourcePath = data.getPayload().toString();
logger.info("Send Notification that {} has been {}.", resourcePath, reason.toLowerCase());
if (resourcePath != null && !resourcePath.isEmpty()) {
ResourceInfo resourceInfo = new ResourceInfo(resourcePath, baseUrl);
sendEmail(resourceInfo, reason);
}
}
} catch (EmailException ex) {
logger.warn("Failed to send Email");
throw new WorkflowException(ex);
} catch (MailingException ex) {
logger.warn("Failed to send Email");
throw new WorkflowException(ex);
}
}
}
You can find more info in the documentation for Extending Workflow Functionality.
Look at the first code block on that page, and that will give you the best idea of how you can implement a custom workflow handler.
EDIT
If you want to see it on the front-end, you could do an AJAX call to get the JSON list of currently running workflows - you can hit this url:
http://localhost:4502/etc/workflow/instances.RUNNING.json
Then you could loop through them and see if yours is in there. This isn't very nice though, since they are all just listed by IDs. I would instead suggest using the querybuilder, or again, just doing an AJAX GET. This is one example:
1_group.0_path=/etc/workflow/instances
2_group.0_type=cq:Workflow
0_group.property.2_value=COMPLETED
0_group.property=status
0_group.property.and=true
3_group.property=modelId
3_group.property.2_value=/etc/workflow/models/your-model-name/jcr:content/model
3_group.property.and=true
Then the URL would look something like this:
http://yoursiteurl:port/libs/cq/search/content/querydebug.html?_charset_=UTF-8&query=http%3A%2F%2Fyoursiteurl%3Aport%3F%0D%0A1_group.0_path%3D%2Fetc%2Fworkflow%2Finstances%0D%0A2_group.0_type%3Dcq%3AWorkflow%0D%0A0_group.property.2_value%3DRUNNING%0D%0A0_group.property%3Dstatus%0D%0A0_group.property.and%3Dtrue%0D%0A3_group.property%3DmodelId%0D%0A3_group.property.2_value%3D%2Fetc%2Fworkflow%2Fmodels%2Fyour-model-name%2Fjcr%3Acontent%2Fmodel%0D%0A3_group.property.and%3Dtrue
It's ugly, but it gets you the results you need, and then you can parse them to get further information you need.

JAX-RS modifying project /tomcat

I've been reading a lot on StackOverflow but this is my first question! I've read the rules but bear with me if I miss something :). Don't hesitate to let me know if I'm missing something in my question.
I'm trying to learn jax-rs but it is a little bit confusing as I'm new to it. I'm trying mykong's tutorial and it works ok.
I've been working under Eclipse and here is the exact code from the tutorial that I have :
package com.mkyong.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
#Path("/hello")
public class HelloWorldService {
#GET
#Path("/{param}")
public Response getMsg(#PathParam("param") String msg) {
String output = "Jersey say : " + msg;
return Response.status(200).entity(output).build();
}
}
I've been trying just to modify the line with :
String output = "Jersey say : " + msg;
to let'say :
String output = "Another message : " + msg;
When I restart Tomcat in Debug, it still gives me "Jersey say :..." message, even in Debug when I look in the output value, it gives me this value...
Do I have to republish? or maybe delete the server and reconfigure one each time I modify the source code?
Thank you in advance!
This tutorial may help you configure it : http://ducquoc.wordpress.com/2010/11/06/eclipse-wtp-tomcat-hot-deploy/