I want to split a very large string into multiple lines. When I use next line characters, those characters are displayed in Swagger UI without having multiple lines.
Code is as below:
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
#Path("test")
#Api(tags = {"Testing"})
public class TestingService {
#Context
private HttpServletRequest request;
#GET
#Path("testing")
#Produces(MediaType.APPLICATION_JSON)
#ApiOperation(value = "Testing",
response = String.class)
public String getString(
throws Exception {
return "abcdef,fghijk";
}
}
Input is:
abcdef,fghijk
Current Output:
{
"messages": "abcdef,fghijk"
}
Expected Output:
{
"messages": "abcdef,
fghijk"
}
I have tried \n, \\n, \\\n and \r\n.
Note: I am using Jersey Framework for this REST API & Swagger for UI.
Thanks a lot in advance for the help.
Workaround :
(a) split the string on some basis
(b) create a list of object where object stores the split string.
(c)Send the list to UI as response.
Output will be as below:
{
"messages_list": [
{"message": "abcdef"},
{"message": "fghijk"}
]
}
Note: This was not the actual requirement. This is just workaround to display long & different messages in different lines.
Related
I am developing a Rest-API application using Java/Quarkus. My POST API accepts XML/JSON contents. I would like to identify the type of MediaType of the incoming data based on which I need to make a request to another URL by setting the appropriate content-type.
Following is the code I have so far:
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
#Path("/api")
public class DataGenerator {
#Path("/generate")
#POST
#Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#Produces(MediaType.APPLICATION_JSON)
public String generateData(String input) throws IOException, InterruptedException {
final HttpRequest request = HttpRequest.newBuilder(URI.create("https://example.com/example"))
.header("content-type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(input))
.build();
return HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()).body();
}
}
As you can see my input can be XML/JSON. If JSON then I would like to set header("content-type", "application/json") else if the input is XML then I would like to set header("content-type", "application/xml").
Based on the content-type the URL https://example.com/example calls out a different method to generate the response.
As of now, the function is working accurately for JSON but I am unable to handle the XML Input. Can someone please let me know how can I find the incoming Input MediaType?
I have this question for spring-boot (Find the Content-type of the incoming request in Spring boot) but I am unable to understand how to do it for the Quarkus-based application? Do I need to pass again from front-end or there is some Quarkus default way?
Usually, this is set in the Content-Type header. So to pull this header you can do this (this uses JAX-RS annotation javax.ws.rs.HeaderParam):
#POST
#Produces(MediaType.TEXT_PLAIN)
#Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public String hello(#HeaderParam("Content-Type") String contentType, String data) {
return String.format("Data: %s%nContent-Type: %s", data, contentType);
}
Just for learn, I'm trying understand a better way to create a JSON response. I expect the following output on my request:
HTTP/1.1 200 OK
Content-Length: 15
Content-Type: application/json
connection: close
{
"status": "ok"
}
Using Java for this task (In this case Quarkus), I have the follow code:
package br.com.bb.feedback.Controller;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.GET;
import javax.ws.rs.core.Response;
import javax.json.JsonObject;
import javax.json.Json;
#Path("/health-check")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class HealthCheckController {
#GET
public Response check() {
JsonObject health = Json.createObjectBuilder().add("status", "ok").build();
return Response.status(Response.Status.OK).entity(health).build();
}
}
So, to build the entity object I use Json.createObjectBuilder(). Have a better way to do this?
"Better" way is a matter of opinion, but there are easy to use alternate ways:
Using a Map. In Java 9+, that's really easy:
#GET
public Response check() {
return Response.status(Response.Status.OK)
.entity(Map.of("status", "ok"))
.build();
}
In Java 8 or earlier, it takes a bit extra:
#GET
public Response check() {
Map<String, String> health = new HashMap<>();
health.put("status", "ok");
return Response.status(Response.Status.OK).entity(health).build();
}
Using a POJO:
#GET
public Response check() {
return Response.status(Response.Status.OK)
.entity(new Health("ok"))
.build();
}
static final class Health {
private String status;
// constructors, getters, and setters here
}
Say I have this resource:
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
#Path("/authhello")
#Api(value = "hello", description = "Simple endpoints for testing api authentification",
hidden = true)
#Produces(MediaType.APPLICATION_JSON)
#RequiresAuthentication
public class AuthenticatedHelloWorldResource {
private static final String READ = "READ";
private static final String WRITE = "WRITE";
#GET
#ApiOperation(value = "helloworld",
notes = "Simple hello world.",
response = String.class)
#RequiresRoles(READ)
public Response helloWorld() {
String hello = "Hello world!";
return Response.status(Response.Status.OK).entity(hello).build();
}
#GET
#Path("/{param}")
#ApiOperation(value = "helloReply",
notes = "Returns Hello you! and {param}",
response = String.class)
#RequiresRoles(WRITE)
public Response getMsg(#PathParam("param") String msg) {
String output = "Hello you! " + msg;
return Response.status(Response.Status.OK).entity(output).build();
}
}
Should I write tests that confirm that certain (test) users get a response from the endpoints, and certain users don't? And if so: How can I write those tests? I've tried something like this:
import javax.ws.rs.core.Application;
import org.glassfish.jersey.server.ResourceConfig;
import org.junit.Test;
import com.cognite.api.shiro.AbstractShiroTest;
import static org.junit.Assert.assertEquals;
public class AuthenticatedHelloWorldTest extends AbstractShiroTest {
#Override
protected Application configure() {
return new ResourceConfig(AuthenticatedHelloWorldResource.class);
}
#Test
public void testAuthenticatedReadHelloWorld() {
final String hello = target("/authhello").request().get(String.class);
assertEquals("Hello world!", hello);
}
#Test
public void testAuthenticatedWriteHelloWorld() {
final String hello = target("/authhello/test").request().get(String.class);
assertEquals("Hello you! test", hello);
}
}
but I'm not sure how to actually test the function of the #RequiresRoles-annotation. I've read Shiro's page on testing, but I haven't been able to write a failing test (e.g. a test for a subject that does not have the WRITE role trying to access /authhello/test). Any tips would be appreciated.
Should I even test this?
Yes. Provided you want to make sure that certain roles will have or have not access to your resource. This will be a security integration test.
How should I go about setting up the whole application + actually call it with an http request in a test if I am to test it? Or is there a simpler way?
Part of the issue is that #RequiresAuthentication and #RequiresRoles themselves are just class and method meta information. Annotations themselves do not provide the security check functionality.
It is not clear from your question what type of container you are using but I can guess that it is plain Jersey JAX-RS service (am I right?). For Shiro to perform security checks you should have added some JAX-RS filter (maybe some other way?) around your endpoints. To test security you should replicate this setup in your tests. Otherwise there is no engine processing your annotations and no security checks as the result.
I am following a tutorial and also used the Stackoverflow question here.
Here is my Java class:
package com.crunchify.tutorial;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import org.json.simple.JSONObject;
#Path("api")
public class CrunchifyAPI {
#SuppressWarnings("unchecked")
#GET
#Path("/get")
#Consumes(MediaType.TEXT_PLAIN)
public String get(
#DefaultValue("111") #QueryParam("user") int user,
#Context UriInfo uriInfo
) {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
String nameParam = queryParams.getFirst("user");
System.out.println("Data Received: " + uriInfo.getRequestUri().getQuery()
+ " | " + nameParam);
JSONObject obj = new JSONObject();
obj.put("auth", true);
String ret = JSONObject.toJSONString(obj);
return ret;
}
}
Following is what I am GET'ing from postman:
GET>> localhost/api/get?user=123
Response is:
{"auth":true}
Server console:
Starting Crunchify's Embedded Jersey HTTPServer...
Started Crunchify's Embedded Jersey HTTPServer Successfully !!!
Data Received: ?user=123 | null
User Authenticated: true
I have tried with passing String, Integer etc but nothing works. The uri Info is getting printed correctly and the response back is also fine. The issue is that I am not getting the parameter to be read in Java Code. I will need to pass many other parameters once I am able to get this going. Please suggest. Thanks!!
I think you're trying too hard. As far as I can tell, doing the following should get you what you want if you call localhost/api/get?user=123:
package com.crunchify.tutorial;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import org.json.simple.JSONObject;
#Path("api")
public class CrunchifyAPI {
#SuppressWarnings("unchecked")
#GET
#Path("/get")
#Consumes(MediaType.TEXT_PLAIN)
public String get(
#DefaultValue("111") #QueryParam("user") Integer user,
#Context UriInfo uriInfo
) {
System.out.println("Data Received: " + uriInfo.getRequestUri().getQuery()
+ " | " + name);
JSONObject obj = new JSONObject();
obj.put("auth", true);
String ret = JSONObject.toJSONString(obj);
return ret;
}
}
All that extra stuff with the query string isn't needed if all you need is the information passed in the user parameter.
#QueryParam("user") int user
the value of that user int should be 123
See https://www.mkyong.com/webservices/jax-rs/jax-rs-queryparam-example/
Well, I think you're having a problem with Java Types.
If your user is an Integer you should pass it to String first if you want to work with a String (Integer.toString() or String.valueof()).
But the way you're passing the parameter is bothering me, I'm not sure if you can pass integers by text plain medi types.
New to java programming and still learning. I've built a RESTful service and I'm trying to pass in a parameter for a GET routine and I'm getting back a state 400 saying that the "Request entity cannot be empty". When I call the non-parameterized GET, the data comes back just fine. I've stripped down all the functionality of the parameterized GET to just return a simple string and I'm still getting the same message. Searched all over and can't find anything that's very helpful.
Below is the code that I'm running for the service. The method "GetChildAllInfo" makes a call to a local mySQL instance and returns a list of objects; that one works just fine. The parameterized one returns nothing, not even an exception.
Any help would be tremendously appreciated. Even if it's a ridiculously simple solution like a syntax error that I may have missed. AND I'm willing to accept any other advice on what you see in the code as well. Thanks!
package allowanceManagerChild;
import java.util.Set;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PUT;
import javax.ws.rs.core.MediaType;
import com.google.gson.Gson;
#Path("allowanceManagerChild")
public class AllowanceManagerChild {
#Context
private UriInfo context;
/**
* Creates a new instance of AllowanceManagerChild
*/
public AllowanceManagerChild() {
}
#GET
#Produces(MediaType.APPLICATION_JSON)
public String getJson() {
String response = "";
Set<Child> children = Child.GetAllChildInfo();
for (Child child : children){
Gson gson = new Gson();
String json = gson.toJson(child);
response = response + json;
}
return response;
}
#GET
#Path("/{childID}")
#Produces(MediaType.APPLICATION_JSON)
public String getJson(int childID) {
String response = "";
try{
// Set<Child> children = Child.GetChildInfo(id);
// for (Child child : children){
// Gson gson = new Gson();
// String json = gson.toJson(child);
// response = response + json;
// }
response = "Made it here"; //Integer.toString(childID);
}
catch(Exception e){
response = e.toString();
}
return response;
}
/**
* PUT method for updating or creating an instance of AllowanceManagerChild
* #param content representation for the resource
*/
#PUT
#Consumes(MediaType.APPLICATION_JSON)
public void putJson(String content) {
}
}
Adding the #PathParam annotation to the method parameter might help:
#GET
#Path("/{childID}")
#Produces(MediaType.APPLICATION_JSON)
public String getJson(#PathParam("childID") int childID) {
See the RESTful Web Services Developer's Guide for more details.