I have created a RestfulWeb Service in Java that is working well with GET requests. However I cannot find some good resource on how to make it accept POST requests.
This is how I run GET
#Path("/hello")
public class Hello {
#GET
#Path(value = "/ids/{id}")
public String ids(#PathParam(value = "id") final String id) throws JSONException {
return getResults("select * from " + id);
}
In order to access this method from web I just go to mywebservice.com/hello/thisismyID and the method receives the "ID".
How would this look if it was to be done with a POST.
Thanks in advance,
-D
Example
#Path("/hello")
public class Hello {
#POST
#Path(value = "/ids")
public String ids(#HeaderParam("id") final String id) throws JSONException {
return getResults("select * from " + id);
}
}
#Path("/hello")
public class Hello {
#POST
#Path("/ids/{id}")
public String ids(#PathParam("id") final String id) throws JSONException {
return getResults("select * from " + id);
}
}
an exhaustive tutorial can be found here: Vogella_REST
Related
so i have given a task to create a service that connects to a portal bank! i have to send user credit card information and the price to the bank portal ! and its all happens in back-end. meanwhile our company didnt used Spring MVC and so i cant use it also . i ve found a way to redirect without MVC but i cant make it a POST request with a body .
this is my code
#Path("/ag/v1")
public class RedirectTestClass {
#GET
#Path("/redirect")
public Response sourceSerivce(){
URI uri = UriBuilder.fromUri("/ag/v1/bank").build();
return Response.seeOther(uri).type(MediaType.APPLICATION_JSON_TYPE).entity(new BankInfo("mmad", 1)).allow(HttpMethod.POST).build();
}
#POST
#Path("/bank")
public Response destinationBank(#RequestBody BankInfo test){
return Response.ok(test.getTest()+"hoooray").build();
}
public static class BankInfo{
public BankInfo(String test, int integer) {
this.test = test;
this.integer = integer;
}
#JsonProperty
private String test;
#JsonProperty
private int integer;
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
public int getInteger() {
return integer;
}
public void setInteger(int integer) {
this.integer = integer;
}
}
}
when i call the redirect serivce with postman i get 405 Method not Allow! how can i redirect it with POST method and body ?
PS: i know for external URL i need to add scheme to my response builder.
I have the following resource:
#Path("")
public class ReviewsResource {
#Context
private UriInfo context;
#EJB
private ReviewsReadBeanRemote reviewReadServices;
#EJB
private ReviewsBeanRemote reviewServices;
public ReviewsResource() {
}
#GET
#AuthenticateUser
#Produces({MediaType.APPLICATION_JSON})
#Path("cadets/{id}/reviews")
public Response getApprovedReviewsByCadet(#PathParam("id") Long cadetId)
throws EnviosYaException {
return Response.ok(reviewReadServices.getReviewsByCadet(cadetId, State.APPROVED)).build();
}
#GET
#AuthenticateAdministrator
#Produces({MediaType.APPLICATION_JSON})
#Path("reviews")
public Response getReviews(#QueryParam("state") String state,
#QueryParam("start") Date start, #QueryParam("end") Date end)
throws EnviosYaException {
State stateValue = null;
if (state != null && !state.isEmpty()) {
stateValue = State.valueOf(state);
}
return Response.ok(reviewReadServices.getReviews(stateValue, start, end)).build();
}
#GET
#AuthenticateUser
#Produces({MediaType.APPLICATION_JSON})
#Path("clients/{id}/shipments")
public Response getShipmentsPendingReviewByClient(#PathParam("id") Long clientId)
throws EnviosYaException {
return Response.ok(reviewReadServices.getShipmentsPendingReviewsByClient(clientId)).build();
}
}
I can use the getReviews just fine like this:
https://localhost:8181/Gateway-war/reviews
But when I try to hit the others like this:
https://localhost:8181/Gateway-war/cadets/1/reviews
I get 404 Not found.
Is there something wrong with the path? Could it be because of the name of my resource?
I do have another resource that starts like this:
#Path("cadets")
public class CadetsResource {
Could the problem be it tries to look there?
Yes - the other path is interfering. In general I put all of my services in a "namespace" per class. So the ReviewsResource might instead look like:
#Path("/reviews")
public class ReviewsResource {
Then everything within that class has a unique part of the URL. You're already following that pattern in the CadetsResource class - I would recommend using it everywhere.
I have a problem with my REST Controller. If I sent a request with a RequestBody (json) some attributes doesn't arrive the controller, although they was sent and defined at model.
I could find out that it look like an old version of files will be used from the local java web server. As I changed the System.out.println Value at Constructor still the old value was outputed.
public RestController_ApiKey_2_0() {
System.out.println("RestController_ApiKey_2_0 init");
}
I tried the following things bootless:
deleted java web server and did a new installation
cleaned the project and started server again
clean install of project
Does anyone have an idea?
Please provide more code, how do you declare a controller, and what params it can take. Also show a sample request.
Here is an example of a simple controller:
A model
public class CustomRequestBody {
private String fieldA;
private String fieldB;
public String getFieldA() {
return fieldA;
}
public void setFieldA(final String fieldA) {
this.fieldA = fieldA;
}
public String getFieldB() {
return fieldB;
}
public void setFieldB(final String fieldB) {
this.fieldB = fieldB;
}
}
Controller:
#Controller
public class MyController {
#RequestMapping(value = "/some-path", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.ACCEPTED)
public ResponseEntity handleSomePath(#RequestBody final CustomRequestBody body, final HttpServletRequest request) {
// Do the job.
}
And request will be:
HTTP POST http://some.server.com/some-path
{
"fieldA":"first value",
"fieldB":"second value"
}
Read more at Spring documentation here
For some reason, the second and the subsequent Query Parameters are just null. The first one works perfectly fine. I am using Camel+JAX-RS (CXF). This is just a GET request. The URL I am using is
http://localhost:8181/cxf/coreservices/search?q=health&start=100&size=924
Here is my Interface declaration
#Path("search")
public interface SearchRestService {
#GET
#Produces(MediaType.APPLICATION_JSON)
public String searchGet(#QueryParam ("q") String q, #DefaultValue("0") #QueryParam("start") String start, #DefaultValue("10") #QueryParam("size") String size );
Implementation
public SearchResult<WikiSearchHit> searchGet(String q, String start, String size){
logger.info("Inside wiki GET method: " +q + " start:"+start + " size:"+ size);
The q parameter comes in fine as health but the start and the size parameters are just null. Surprisingly, the default values aren't getting picked up too.
I am afraid I am doing something wrong in my camel routing.
Router
#Override
public void configure() throws Exception {
from("cxfrs://bean://rsServer?bindingStyle=SimpleConsumer")
.multicast()
.parallelProcessing()
.aggregationStrategy(new CoreSearchResponseAggregator())
.beanRef("searchRestServiceImpl", "searchGet")
...
Thanks for your time :-)
The Camel team is working on fixing this issue in the near future. Until then use the following workaround.
You could get the entire query string as follows
String query = exchange.getIn().getHeader(Exchange.HTTP_QUERY, String.class);
//would return something like : q=health&start=100&size=924
Interface
#GET
#Path("search")
#Produces(MediaType.APPLICATION_JSON)
public String searchGet();
Implementation - Target method
public SearchResult<WikiSearchHit> wikiGet(Exchange exchange){
String q = exchange.getIn().getHeader("q", String.class);
String size = exchange.getIn().getHeader("size", String.class);
String start = exchange.getIn().getHeader("start", String.class);
Router
public class RestToBeanRouter extends RouteBuilder {
#Override
public void configure() throws Exception {
from("cxfrs://bean://rsServer?bindingStyle=SimpleConsumer")
.process(new ParameterProcessor())
.removeHeaders("CamelHttp*")
.multicast()
.parallelProcessing()
.aggregationStrategy(new CoreSearchResponseAggregator())
.beanRef("searchRestServiceImpl", "wikiGet")
....
.end()
.marshal().json(JsonLibrary.Jackson);
//.to("log://camelLogger?level=TRACE");
}
class ParameterProcessor implements Processor {
#Override
public void process(Exchange exchange) throws Exception {
Map<String, String> stringStringMap = convertQueryStringAsMap(exchange.getIn().getHeader(Exchange.HTTP_QUERY, String.class));
//System.out.println("stringStringMap = " + stringStringMap);
for (Map.Entry<String, String> eachParamEntry : stringStringMap.entrySet()) {
exchange.getIn().setHeader(eachParamEntry.getKey(), eachParamEntry.getValue());
}
}
private Map<String,String> convertQueryStringAsMap(String queryString){
//some Guava magic
return Splitter.on("&").omitEmptyStrings().trimResults().withKeyValueSeparator("=").split(queryString);
}
}
}
More details here :
http://camel.465427.n5.nabble.com/JAX-RS-and-Camel-Except-1st-QueryParameter-all-others-are-null-tt5742470.html
I have developed a simple RESTful web service.
Root Resource Class:
#Path("/order")
#RequestScoped
public class CustOrderContainerResource {
//<editor-fold defaultstate="collapsed" desc="Instance Variable">
#Context
private UriInfo myUriInfo;
#Context
private ResourceContext myResourceContext;
#Context
private SecurityContext mySecurityContext;
#Inject
private CustOrderDAO myCustOrderDAO;
public CustOrderContainerResource() {
}
#GET
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML})
public List<Custorder> ReadCustomerOrder(#QueryParam("min")int min,
#QueryParam("max")int max, #Context Request myRequest,
#Context HttpHeaders myHeader) {
int totalOrder = 0;
List<Custorder> resultList = null;
totalOrder = myCustOrderDAO.count();
if(min == 0 && max == 0) {
throw new QueryParamException("Order ID is empty");
}
else if(max > totalOrder) {
throw new QueryParamException("Order ID Range is invalid");
}
resultList = myCustOrderDAO.findRange(min, max, "findOrderIDRange");
return resultList;
}
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Custorder> ReadCustomerOrder() {
// Check conditional get here
return myCustOrderDAO.findAll();
}
#POST
#Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_FORM_URLENCODED})
public Response createOrder(Custorder myCustOrder) {
String orderID = null;
myCustOrder.setStatus("pending");
myCustOrder.setOrderdate(new Date());
myCustOrder.setTotal("");
// Persist
myCustOrderDAO.create(myCustOrder);
// Get Order ID
// Embedded created URL for new customer order in response
return Response.created(myUriInfo.getAbsolutePath().resolve(myCustOrder.getOrderid() + "/")).build();
}
#Path("{orderID}")
// #Produces(MediaType.TEXT_HTML)
public CustOrderResource ReadSingleCustomerOrder(#PathParam("orderID") String orderID) {
int userOrderID = Integer.parseInt(orderID);
int myOrderID = myCustOrderDAO.count();
CustOrderResource myCustorder = null;
if(userOrderID > myOrderID
|| myCustOrderDAO.find(orderID) == null) {
throw new OrderNotFoundException("Order ID Not Found");
}
if(!mySecurityContext.isUserInRole("admin")) {
// Propogates to specific resource class
myCustorder = myResourceContext.getResource(CustOrderResource.class);
myCustorder.setOrderID(orderID);
}
return myCustorder;
// return CustOrderResource.getInstance(myCustOrderDAO, orderID);
}
}
Sub Resource Locator Class :
#RequestScoped
public class CustOrderResource {
//<editor-fold defaultstate="collapsed" desc="Instance Variable">
#Inject
private CustOrderDAO myCustOrderDAO;
private String orderID;
private static final Logger myLogger = Logger.getLogger(CustOrderResource.class.getName());
//</editor-fold>
// ========================================================
public CustOrderResource() {
}
private CustOrderResource(String orderID) {
this.orderID = orderID;
}
public static Custorder getInstance(CustOrderDAO myCustOrderDAO, String orderID) {
return myCustOrderDAO.find(orderID);
}
#GET
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_ATOM_XML})
public Custorder getCustomerOrder() {
return myCustOrderDAO.find(orderID);
}
#POST
#Consumes(MediaType.APPLICATION_XML)
public String updateCustomerOrder() {
return "so";
/*try {
myCustOrderDAO.update(myCustOrder);
}
catch(Exception e) {
myLogger.log(Level.ALL, e.toString());
throw new WebApplicationException(
Response.status(Status.INTERNAL_SERVER_ERROR)
.entity("Cust Order Update Failed").build());
}*/
}
#DELETE
// 415 Unsupported media type
public String deleteCustomerOrder() {
return "Deleted";
// myCustOrderDAO.delete(myCustOrder);
}
public String getOrderID() {
return orderID;
}
public void setOrderID(String orderID) {
this.orderID = orderID;
}
}
My question is
AFAIK, the resource context will propagate to specific resource class
when we specify it as an argument according to the HTTP method like
POST or DELETE. How do I pass the parameter from sub resource locator
method into sub resource class method?
I tried to update customer order using post method with XML data but unfortunately the JAX-RS runtime returns 415 Unsupported media type.
I am using the REST client from http://code.google.com/p/rest-client/ to test my application, by pasting an XML file into the body tab content. What is wrong with it?
Does the JAXB automatically convert to XML when I return a list of
objects? I have tested and it return xml format but just want
confirmation. Is it more flexible to return response object?
I wonder how to build a response object with list of object and list of URI or Atom XML with list of object (Apache Abdera).
How to find out a id of a newly persisted object into database in my
createCustomerOrder method ?
Thanks.
Please help.
Passing object into sub resource locator class is solve by using QueryParam annotation. Newly persisted object is finding using EntityManager util.