I need Wicket to respond to a post request from AngularJS.
I set up a page in wicket like this but the request parameters are always empty
#MountPath(value = "/api/my/rest/url")
public class MyPostHandler extends SecureWebPage {
public MyPostHandler () {
final WebRequest webRequest = (WebRequest) getRequest();
final HttpServletRequest rawRequest = (HttpServletRequest) webRequest.getContainerRequest();
if (rawRequest.getMethod().equalsIgnoreCase("POST")) {
webRequest.getRequestParameters().getParameterNames(); //Returns an empty list
webRequest.getPostParameters().getParameterNames(); //Returns an empty list
}
}
}
The AngularJS code that is sending the POST request looks like this:
$http.post('/api/my/rest/url', {some:"data", other:"stuff"});
Any idea what's going wrong here?
Thanks!
Not sure if this is the best solution but the following code is working for me
#MountPath(value = "/api/my/rest/url")
public class MyPostHandler extends SecureWebPage {
public MyPostHandler () {
final WebRequest webRequest = (WebRequest) getRequest();
final HttpServletRequest rawRequest = (HttpServletRequest) webRequest.getContainerRequest();
if (rawRequest.getMethod().equalsIgnoreCase("POST")) {
BufferedReader br;
try {
br = rawRequest.getReader();
String jsonString = br.readLine();
//Do something with the JSON here
}
catch (IOException e) {
}
}
}
}
Another potential solution I came across was this project https://github.com/bitstorm/Wicket-rest-annotations
WicketStuff REST Annotations can help accomplishing this with built-in support for JSON serialization/deserialization.
I used Wicket rest annotaions in one of my projects. Here is its the Maven repository. Please find below an example:
pom.xml
<dependency>
<groupId>org.wicketstuff</groupId>
<artifactId>wicketstuff-restannotations</artifactId>
<version>8.1.0</version>
</dependency>
<dependency>
<groupId>org.wicketstuff</groupId>
<artifactId>wicketstuff-restannotations-json</artifactId>
<version>8.1.0</version>
</dependency>
Create your Wicket REST resource:
import org.wicketstuff.rest.annotations.MethodMapping;
import org.wicketstuff.rest.annotations.parameters.RequestBody;
import org.wicketstuff.rest.resource.gson.GsonRestResource;
import org.wicketstuff.rest.utils.http.HttpMethod;
public class MyPostHandler extends GsonRestResource {
#MethodMapping(value = "/my/rest/url", httpMethod = HttpMethod.POST)
public boolean handlePost(#RequestBody SomeObject someObject) {
...
}
}
And in your Wicket WebApplication init() method, register the rest resource:
mountResource("/api", new ResourceReference("restReference") {
MyPostHandler resource = new MyPostHandler();
#Override
public IResource getResource() {
return resource;
}
});
Once the REST web service is up running, you can issue HTTP POST request:
POST URL: http://localhost:8080/api/my/rest/url
POST data: {json data for SomeObject}
Content-Type: application/json
That's it.
Related
I have created a REST api which can used to save different urls those url have auto-increment feature that assign them an id one endpoint is to add urls and other is to fetch urls from id
I want to do something like if I pass localhost:8080/getUrlById?id=4/ my browser should redirect me to that url which is there at 4th no.
my controller code -
#GetMapping("/addUrl")
public ResponseEntity<?> addUrlByGet(String url) {
return new ResponseEntity<>(sortnerService.addUrlByGet(url),HttpStatus.OK);
}
#GetMapping("/findUrlById")
public ResponseEntity<?> findSortnerById(Integer id){
return new ResponseEntity<>(sortnerService.findUrlById(id), HttpStatus.OK);
}
service class -
#Service
public class SortnerService {
#Autowired
private SortnerRepo sortnerRepo;
public Sortner addUrlByGet(String url) {
Sortner sortner = new Sortner();
sortner.setUrl(url);
return sortnerRepo.save(sortner);
}
// finding by particular Id
public List<Sortner> findUrlById(Integer id){
return sortnerRepo.findSortnerById(id);
}
}
Can anyone suggest me any way to do it I am really new to SpringBoot Sorry if I have made any silly mistake.
Based on the information from the comments, I suggest that the Sortner class looks like this:
public class Sortner {
Long id;
URL url;
}
So to redirect to the URL by the Id from your service you need to rewrite your controller to look like this:
#GetMapping("/findUrlById")
public void findSortnerById(Integer id, HttpServletResponse response) throws IOException {
List<Sortner> urls = sortnerService.findUrlById(id);
if(urls != null && urls.size() > 0) {
response.sendRedirect(urls.get(0).getUrl().toString());
}
response.sendError(HttpServletResponse.SC_NOT_FOUND)
}
response.sendRedirect redirects to the required URL
response.sendError returns 404 as the URL cannot be found in the database
We want to deliver some HTML files as well as other files through a Spring Boot Webapp. We want to split the HTML and non HTML traffic by craeting a REST endpoint just for URIs that end with .html.
We tried something like this without success :(
#GetMapping(value = "/{*html}")
public String deliverHtml(HttpServletResponse response, HttpServletRequest request) {
return doSomeMagicStuff();
}
#GetMapping(value = "{*filepaths}/{*html}")
public String deliverHtml2(HttpServletResponse response, HttpServletRequest request) {
return doSomeMagicStuff();
}
Unfortunately the above code and some other variations do not work
This code worked fine for me. Notice, that for your purposes you can use just ant-patterns (instead of real regexp).
#RestController
#RequestMapping("filter-content")
public class FilterController {
#PostMapping(value = "*.xml")
public void onlyXml() {
System.out.println("Xml content");
}
#PostMapping(value = "*.html")
public void onlyHtml() {
System.out.println("Html content");
}
#PostMapping(value = "*")
public void otherContent() {
System.out.println("Other content");
}
}
P.S.: Also consider using of POST requests for "delivering" content.
In the end I was not finding an answer to the original question so I used this
#RequestMapping(value = "**")
To catch all request that were not handeled by a dedicated mapping and then I did the split of HTML and non HTML in plain Java Code...
I have made my rest web service code to start sever like this :
static final String BASE_URI = "http://10.236.51.14:9000/abcd/";
public static void main(String[] args) {
try {
HttpServer server = HttpServerFactory.create(BASE_URI);
server.start();
System.out.println("Press Enter to stop the server. ");
System.in.read();
server.stop(0);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
And in the rest web service I have made a basic code to receive 2 arguments and show their sum like this :
#GET
#Path("/add/{a}/{b}")
#Produces(MediaType.TEXT_XML)
public String add(#PathParam("a") double a, #PathParam("b") double b) {
return "<?xml version=\"1.0\"?>" + "<result>" + (a + b) + "</result>";
}
I want to send Json data (image) from my android app to this webservice but I don't know how to receive it in webservice and display it.
Here is the code from my android app. In this I have converted a bitmap to string using Base64. How should I send it to my webservice?
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mybitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String strBitMap = Base64.encodeToString(b, Base64.DEFAULT);
Any help will be appreciated :)
I have searched a lot but cant find appropriate code for my webservice to receive and display the json data. I am also struggling in sending this base64 string to the webservice in form of json.
Please help me out.
Best regards :)
I have a question: Does your example WebService work? I mean the one with the two arguments. If you call http://10.236.51.14:9000/abcd/add/1/2 in your browser does it display 3 correctly? If not you should have an ApplicationConfig containing your REST-interfaces. Those should be added as resource classes for example like this:
#ApplicationPath("api")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet<>();
resources.addAll(addServiceClasses());
resources.addAll(addFilterClasses());
return resources;
}
private Set<Class<?>> addServiceClasses() {
// add all your REST-classes here
Set<Class<?>> resources = new HashSet<>();
resources.add(YourCalculatorRestServiceClass.class);
resources.add(YourImageConsumingRestServiceClass.class);
return resources;
}
private Set<Class<?>> addFilterClasses() {
// add all your filter classes here (if you have any)
Set<Class<?>> resources = new HashSet<>();
resources.add(YourAuthenticationFilterClass.class);
resources.add(OtherFilterClass.class);
return resources;
}
#Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<>();
// in Jersey WADL generation is enabled by default, but we don't
// want to expose too much information about our apis.
// therefore we want to disable wadl (http://localhost:8080/service/application.wadl should return http 404)
// see https://jersey.java.net/nonav/documentation/latest/user-guide.html#d0e9020 for details
properties.put("jersey.config.server.wadl.disableWadl", true);
// we could also use something like this instead of adding each of our resources
// explicitly in getClasses():
// properties.put("jersey.config.server.provider.packages", "com.nabisoft.tutorials.mavenstruts.service");
return properties;
}
}
That should make the deal and you should be able to call http://10.236.51.14:9000/abcd/api/add/1/2. ApplicationConfig is annotated with #Path("api"). That means all classes registered in this config have the root path http://your.server.address/api/.
Now to your problem. I assume your server is working and you can reach your Webservice /add/1/2 displaying the result 3 in your browser.
Now you need another service listening for a POST. I'd take your already prepared String as the posted body.
#Path("image")
public class ImageReceiverRestService {
#POST
public Response checkAssignable(String base64ImageString) {
// code here working with the base64ImageString
// response code according to whatever happened during your algorithm
return Response.ok().build();
}
}
For appropriate HTTP response codes see this Wikipedia article for a quick overview HTTP Status Codes
So now you'd need a corresponding client on your android app. For example:
public class ImageSendingRestClient {
private final static String SERVER_BASE_URI = "http://10.236.51.14:9000/abcd/api/";
private final static String API_ADDRESS = "image/";
public ImageSendingRestClient() {
}
#Override
public void sendImageStringForProcessing(String base64ImageString) throws Exception {
Entity<String> entity = Entity.json(base64ImageString);
Response response = ClientBuilder.newClient()
.target(SERVER_BASE_URI)
.path(API_ADDRESS)
.request()
.post(entity);
try {
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
return;
}
if (response.getStatus() == Response.Status.NOT_FOUND.getStatusCode()) {
throw new Exception;
}
} finally {
response.close();
}
}
}
All dependencies needed are JAX-RS implementations like JAX-RS reference implementation Jersey. Maybe you should also check the Jersey Guide with many examples providing most of the information you need Jersey User Guide
I've been writing simple dropwizard application, and everything worked fine, untill I had to change request type. As I previously got my arguments from Header, now I have to get them from the body of a JSON request. And the saddest part is - there is no complete documentation for dropwizard or any article, that would help me. Here's my code:
#Path("/actors")
#Produces("application/json")
public class ActorResource {
private final ActorDAO dao;
public ActorResource(ActorDAO dao) {
this.dao = dao;
}
#POST
#UnitOfWork
public Saying postActor(#HeaderParam("actorName") String name,#HeaderParam("actorBirthDate") String birthDate) {
Actor actor = dao.create(new Actor(name,birthDate));
return new Saying("Added : " + actor.toString());
}
Does anyone have a solution?
as requested, here's a snippet demonstrating what you want to do:
#Path("/testPost")
#Produces(MediaType.APPLICATION_JSON)
public class TestResource {
#POST
public Response logEvent(TestClass c) {
System.out.println(c.p1);
return Response.noContent().build();
}
public static class TestClass {
#JsonProperty("p1")
public String p1;
}
}
The TestClass is my body. Jersey knows right away, that it needs to parse the body into that object.
I can then curl my API doing this:
curl -v -XPOST "localhost:8085/api/testPost" -H "Content-Type: application/json" -d '{"p1":"world"}'
Jersey knows by the method parameter what to do, and by the Jackson Annotation how to treat the JSON.
Hope that helps,
Artur
Edit: For the more manual approach, you can:
In your post method, inject
#Context HttpServletRequest request
And from the injected request, write the body into a String for handling:
StringWriter writer = new StringWriter();
try {
IOUtils.copy(request.getInputStream(), writer);
} catch (IOException e) {
throw new IllegalStateException("Failed to read input stream");
}
Now use any library to map that string to whatever Object you want.
I have a Jersey 2 application containing resources that consume and produce json. My requirement is to add a signature to an Authorization response header generated from a combination of various piece of response data (similar to the Amazon Webservices request signature). One of these pieces of data is the response body but I cant see that there are any filter or interception points that will allow me access to the json content. I imagine this is mainly because the response outputstream is for writing not reading.
Any ideas as to how I can read the response body - or alternative approaches ?
Thank you.
My understanding is that when your application is responding to a request, you want to modify the Authorization header by adding a signature to it's value.
If that's the case, you want to implement a ContainerResponseFilter:
public class MyContainerResponseFilter implements ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
// You can get the body of the response from the ContainerResponseContext
Object entity = containerResponseContext.getEntity();
// You'll need to know what kind of Object the entity is in order to do something useful though
// You can get some data using these functions
Class<?> entityClass = containerResponseContext.getEntityClass();
Type entityType = containerResponseContext.getEntityType();
// And/or by looking at the ContainerRequestContext and knowing what the response entity will be
String method = containerRequestContext.getMethod();
UriInfo uriInfo = containerRequestContext.getUriInfo();
// Then you can modify your Authorization header in some way
String authorizationHeaderValue = containerResponseContext.getHeaderString(HttpHeaders.AUTHORIZATION);
authorizationHeaderValue = authorizationHeaderValue + " a signature you calculated";
containerResponseContext.getHeaders().putSingle(HttpHeaders.AUTHORIZATION, authorizationHeaderValue);
}
}
Be warned that the filter function will be called for all requests to your application, even when Jersey couldn't find a matching resource for the request path, so you may have to do some extra checking.
You can implement ContainerRequestFilter in order to access the content, and once you are finished with your interception logic, forward it to the request. E.g.
import java.io.*;
import com.sun.jersey.api.container.ContainerException;
import com.sun.jersey.core.util.ReaderWriter;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerRequestFilter;
public class ExampleFilter implements ContainerRequestFilter {
#Override
public ContainerRequest filter(ContainerRequest req) {
try(InputStream in = req.getEntityInputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();) {
if (in.available() > 0) {
StringBuilder content = new StringBuilder();
ReaderWriter.writeTo(in, out);
byte[] entity = out.toByteArray();
if (entity.length > 0) {
content.append(new String(entity)).append("\n");
System.out.println(content);
}
req.setEntityInputStream(new ByteArrayInputStream(entity));
}
} catch (IOException ex) {
//handle exception
}
return req;
}
}