New to Java but fairly knowledgeable about Cucumber.
Here is what my feature steps look like:
#api_test
Feature: Title of your feature
I want to use this template for my feature file
Scenario: Show Blog Post
Given I access the resource url "/comments?id=2"
When I retrieve the results
Then The status code should be 200
And It should have the field "id" containing the value "2"
And It should have the field "email" containing the value "Jayne_Kuhic#sydney.com"
When running feature test, i get following error:
java.lang.Error: Unresolved compilation problems:
wc cannot be resolved
httpStatus cannot be resolved or is not a field
HttpStatusCode cannot be resolved to a variable
WebException cannot be resolved to a type
httpStatus cannot be resolved or is not a field
HttpWebResponse cannot be resolved to a type
HttpWebResponse cannot be resolved to a type
httpStatus cannot be resolved or is not a field
HttpStatusCode cannot be resolved to a variable
Assert cannot be resolved
response cannot be resolved or is not a field
JObject cannot be resolved to a type
JToken cannot be resolved
Here is what my code looks like:
package stepDefinition;
import java.io.*;
import cucumber.api.PendingException;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import org.json.*;
import org.junit.Assert.*;
public class RestTestSteps {
private String url;
private String content;
private WebClient wc = new WebClient();
JObject response;
HttpStatusCode httpStatus;
#Given("^I access the resource url \"([^\"]*)\"$")
public void i_access_the_resource_url(String resourceUrl) throws Throwable {
// Write code here that turns the phrase above into concrete actions
this.url = "http://jsonplaceholder.typicode.com" + resourceUrl;
}
#When("^I retrieve the results$")
public void i_retrieve_the_results() throws Throwable {
// Write code here that turns the phrase above into concrete actions
try
{
this.content = wc.DownloadString(url);
this.httpStatus = HttpStatusCode.OK;
}
catch (WebException we)
{
this.httpStatus = ((HttpWebResponse)we.Response).StatusCode;
}
if (this.httpStatus.Equals(HttpStatusCode.OK))
{
Assert.IsNotNullOrEmpty(this.content);
this.response = (JObject)JToken.Parse(this.content);
}
}
#Then("^The status code should be (\\d+)$")
public void the_status_code_should_be(int statusCode) throws Throwable {
// Write code here that turns the phrase above into concrete actions
Assert.AreEqual(statusCode, (int)this.httpStatus);
}
#Then("^It should have the field \"([^\"]*)\" containing the value \"([^\"]*)\"$")
public void it_should_have_the_field_containing_the_value(String arg1, String arg2) throws Throwable {
// Write code here that turns the phrase above into concrete actions
if (response != null)
{
JValue val = (JValue)this.response.GetValue(field);
string valStr = val.Value().Trim();
Assert.IsNotNull(valStr);
Assert.AreEqual(valStr, value.Trim());
}
}
}
Not sure what im doing wrong here...
It looks to me like you are missing imports. I see imports for the cucumber stuff, but I think you need to import the other classes you are using. If you are in an IDE like eclipse, it should help you add the necessary imports.
Additionally, you didn't import the asserts correctly. Those need to be imported as static.
import static org.junit.Assert.*;
Related
I am developing a Quarkus service-based application for which I am adding open API based annotations such as #ExampleObject. For this, I would like to add the resources file contents as an example that can appear in the SwaggerUI.
I am getting the following error when I add the reference to the files from the resources folder:
Errors
Resolver error at paths./api/generateTestData.post.requestBody.content.application/json.examples.Example1 Schema.$ref
Could not resolve reference: Could not resolve pointer: /Example1.json does not exist in document
Resolver error at paths./api/generateTestData.post.requestBody.content.application/json.examples.Example2 Schema.$ref
Could not resolve reference: Could not resolve pointer: /Example2.json does not exist in document
Following is my Quarkus based Java code:
#RequestBody(description = "InputTemplate body",
content = #Content(schema = #Schema(implementation = InputTemplate.class), examples = {
#ExampleObject(name = "Example-1",
description = "Example-1 for InputTemplate.",
ref = "#/resources/Example1.json"), externalValue = "#/resources/Example2.json"
#ExampleObject(name = "Example-2",
description = "Example-2 for InputTemplate.",
ref = "#/resources/Example1.json") //externalValue = "#/resources/Example1.json"
}))
Note:
I am able to add the String as value but the content for these examples is very large so I would like to read from the files only so trying this approach.
Is there any way I can access the resources file and add it as a ref within my #ExampleObject
A working example below:
Create an OASModelFilter class which implements OASFilter:
package org.acme;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.eclipse.microprofile.openapi.OASFactory;
import org.eclipse.microprofile.openapi.OASFilter;
import org.eclipse.microprofile.openapi.models.Components;
import org.eclipse.microprofile.openapi.models.OpenAPI;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;
import org.eclipse.microprofile.openapi.models.examples.Example;
public class OASModelFilter implements OASFilter {
ObjectMapper objectMapper = new ObjectMapper();
#Override
public void filterOpenAPI(OpenAPI openAPI) {
//openApi.getComponents() will result in NULL as we don't have any openapi.yaml file.
Components defaultComponents = OASFactory.createComponents();
if(openAPI.getComponents() == null){
openAPI.setComponents(defaultComponents);
}
generateExamples().forEach(openAPI.getComponents()::addExample);
}
Map<String, Example> generateExamples() {
Map<String, Example> examples = new LinkedHashMap<>();
try {
//loop over your Example JSON Files,..
//In this case, the example is only for 1 file.
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream userJsonFileInputStream = loader.getResourceAsStream("user.json");
String fileJSONContents = new String(userJsonFileInputStream.readAllBytes(), StandardCharsets.UTF_8);
//Create a unique example for each File/JSON
Example createExample = OASFactory.createExample()
.description("User JSON Description")
.value(objectMapper.readValue(fileJSONContents, ObjectNode.class));
// Save your Example with a Unique Map Key.
examples.put("createExample", createExample);
} catch (IOException ioException) {
System.out.println("An error occured" + ioException);
}
return examples;
}
}
The controller using createExample as its #ExampleObject.
#Path("/hello")
public class GreetingResource {
#GET
#Produces(MediaType.TEXT_PLAIN)
#APIResponses(
value = {
#APIResponse(responseCode = "200", content = #Content(
mediaType = "*/*",
examples = {
#ExampleObject(name = "boo",
summary = "example of boo",
ref = "createExample")
}
))
}
)
public String hello() {
return "Hello RESTEasy";
}
}
In your application.properties, specify the following: Take note that it references the full package path of the Filter.
mp.openapi.filter=org.acme.OASModelFilter
Contents of user.json file:
{
"hello": "world",
"my": "json",
"testing": "manually adding resource JSONs as examples"
}
The JSON file used is located directly under resources. Of course you can change that path, but you need to update your InputStream.
mvn clean install
mvn quarkus:dev
Go to http://localhost:8080/q/swagger-ui/ and you will now see your user.json file contents displayed
Hopes this helps you,
References for my investigation:
https://github.com/labcabrera/rolemaster-core/blob/c68331c10ef358f6288518350c79d4868ff60d2c/src/main/java/org/labcabrera/rolemaster/core/config/OpenapiExamplesConfig.java
https://github.com/bf2fc6cc711aee1a0c2a/kafka-admin-api/blob/54496dd67edc39a81fa7c6da4c966560060c7e3e/kafka-admin/src/main/java/org/bf2/admin/kafka/admin/handlers/OASModelFilter.java
The below works, but as you can see I am creating the PATHS, and you still need to know what the (path/address/is) in order to create paths.
It could help you in thinking in approaching it in a different way.
If you are considering modifying the #ApiResponses/#ApiResponse annotations directly, then it wont work.
package org.acme;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.eclipse.microprofile.openapi.OASFactory;
import org.eclipse.microprofile.openapi.OASFilter;
import org.eclipse.microprofile.openapi.models.Components;
import org.eclipse.microprofile.openapi.models.OpenAPI;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;
import org.eclipse.microprofile.openapi.models.examples.Example;
import io.quarkus.logging.Log;
public class CustomOASFilter implements OASFilter {
ObjectMapper objectMapper = new ObjectMapper();
#Override
public void filterOpenAPI(OpenAPI openAPI) {
//openApi.getComponents() will result in NULL as we don't have any openapi.yaml file.
Components defaultComponents = OASFactory.createComponents();
if (openAPI.getComponents() == null) {
openAPI.setComponents(defaultComponents);
}
generateExamples().forEach(openAPI.getComponents()::addExample);
openAPI.setPaths(OASFactory.createPaths()
.addPathItem(
"/hello/customer", OASFactory.createPathItem()
.GET(
OASFactory.createOperation()
.operationId("hello-customer-get")
.summary("A simple get call")
.description("Getting customer information")
.responses(
OASFactory.createAPIResponses()
.addAPIResponse(
"200", OASFactory.createAPIResponse()
.content(OASFactory.createContent()
.addMediaType("application/json", OASFactory.createMediaType()
.examples(generateExamples()))))))));
}
Map<String, Example> generateExamples() {
Map<String, Example> examples = new LinkedHashMap<>();
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String userJSON = new String(loader.getResourceAsStream("user.json").readAllBytes(), StandardCharsets.UTF_8);
String customerJson = new String(loader.getResourceAsStream("customer.json").readAllBytes(), StandardCharsets.UTF_8);
Example userExample = OASFactory.createExample()
.description("User JSON Example Description")
.value(objectMapper.readValue(userJSON, ObjectNode.class));
Example customerExample = OASFactory.createExample()
.description("Customer JSON Example Description")
.value(objectMapper.readValue(customerJson, ObjectNode.class));
examples.put("userExample", userExample);
examples.put("customerExample", customerExample);
} catch (IOException ioException) {
Log.error(ioException);
}
return examples;
}
}
EDIT: This is working well in spring-boot
The above answer might work but it has too much code to put into to make it work.
Instead, you can use externalValue field to pass on the JSON file.
For example,
#ExampleObject(
summary = "temp",
name =
"A 500 error",
externalValue = "/response.json"
)
And now you can create your json file under /resources/static like below,
Swagger doc screenshot
And that's all you need. You don't need to write any manual code here.
Hope this will help you fix the issue.
I want to verify that id: 1 belongs to Tiger Nixon
{"status":"success","data":[{"id":"1","employee_name":"Tiger Nixon","employee_salary":"320800","employee_age":"61","profile_image":""}
I have been following this document: https://github.com/rest-assured/rest-assured/wiki/Usage#json-using-jsonpath , this section body("shopping.category.find { it.#type == 'groceries' }.item", hasItems("Chocolate", "Coffee"));
Currently I am getting a null pointer exception. I could use some help to come up with a solution. Thanks in advance for your time.
import com.google.gson.JsonObject;
import io.restassured.RestAssured;
import org.testng.Assert;
public class RestAssuredExample_2 {
public void getResponse() {
JsonObject responseObject = RestAssured.get("http://dummy.restapiexample.com/api/v1/employees")
.then()
.extract().response().as(JsonObject.class);
String emp1Name = responseObject.get("data.find{it.#id=='1'}.employee_name").toString();
Assert.assertEquals(emp1Name, "Tiger Nixon");
}
public static void main(String[] args) {
RestAssuredExample_2 rest2 = new RestAssuredExample_2();
rest2.getResponse();
}
}
Error:
Exception in thread "main" java.lang.NullPointerException
at HTTPz.RestAssuredExample_2.getResponse(RestAssuredExample_2.java:16)
Tried to replicate this scenario
String responseObject = RestAssured.get("http://dummy.restapiexample.com/api/v1/employees").then().extract().asString();
JsonPath js = new JsonPath(responseObject);
String emp1Name = js.get("data.find {it.id =='1'}.employee_name").toString();
System.out.println(emp1Name);
And I get the value for emp1Name as "Tiger Nixon"
Difference :
Original : it.#id=='1'
Mine : it.id =='1'
It seems like # is for XMLPath and not for JSONPath and honestly I wouldn't know about it in detail as well cause I have been using JSONPath only for a very long time :)
I am new to groovy way of testing RestController for spring boot application. I have a Controller class :
#RestController
#RequestMapping(value = "/onboarding/v1")
public class OnboardingController {
private static final Logger LOG = LoggerFactory.getLogger(OnboardingServiceImpl.class);
#Autowired
private OnboardingService onboardingService;
#RequestMapping(
value = "/service-models",
method = RequestMethod.POST,
consumes = { "multipart/form-data" },
produces = { "application/json" }
)
public ResponseEntity createServiceModel(
#RequestParam("name") final String name,
#RequestParam("file") final MultipartFile file
){
try {
final ServiceModelRequestData serviceModelRequestData =
new ServiceModelRequestData(name, file);
final ServiceModelDetail createdServiceModel =
onboardingService.createServiceModel(serviceModelRequestData);
return new ResponseEntity<>(createdServiceModel, HttpStatus.OK);
}
catch (MalformedContentException ex) {
LOG.error("Malformed Content:", ex);
return new ResponseEntity<>(errorMessage(ex), HttpStatus.BAD_REQUEST);
}
catch (ServiceModelNameAlreadyExistsException ex) {
LOG.error("Service Model Name Already Exists:", ex);
return new ResponseEntity<>(errorMessage(ex), HttpStatus.CONFLICT);
}
catch (ServiceUnavailableException ex) {
LOG.error("Service Unavailable currently:" + ex);
return new ResponseEntity<>(errorMessage(ex), HttpStatus.SERVICE_UNAVAILABLE);
}
}
//...
}
I am unable to find how to spock test the above class along with writing the spock test cases for exceptions and checking the desired response?I want to create a test case which throws an error when the method is called and returns the responseentity which I want to check contains the given Jason data along with the desired Http Status. Sample spock test for the code snippet would be highly appreciated.
EDITED:
The test Class is as below(along with comments of what I was trying to do):
package com.service.onboarding.web.controller
import spock.lang.Specification
import com.service.onboarding.business.OnboardingServiceImpl
import com.service.onboarding.business.api.OnboardingService
import com.service.onboarding.domain.exception.MalformedContentException
import com.service.onboarding.domain.exception.ServiceModelNameAlreadyExistsException
import com.service.onboarding.domain.exception.ServiceUnavailableException
import com.service.onboarding.domain.resource.Greeting
import groovy.json.internal.Exceptions
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.test.web.servlet.MockMvc
import org.springframework.web.multipart.MultipartFile
import org.springframework.boot.test.mock.mockito.MockBean
import org.springframework.http.ResponseEntity
import spock.lang.Unroll
import static org.mockito.BDDMockito.given
/*#WebMvcTest
public class OnboardingControllerSpec extends Specification {
#MockBean
private OnboardingService onboardingService;
#Autowired
private MockMvc mockMvc;
def "controller should return expected JSON content and OK response"() {
given: 'hello world service responds with greeting'
def name = "Emily"
given(onboardingService.getPersonalGreeting("${name}")).willReturn(new Greeting(1, "Hi, ${name}"));
when: 'hello world service is called with name provided'
def response = mockMvc.perform(get("/onboarding/v1?name=${name}"))
then: 'expected JSON returned and response code is OK'
response
.andExpect(status().isOk())
.andExpect(content().json("{'id': 1, 'content': 'Hi, ${name}'}"))
}
}*/
public class OnboardingControllerSpec extends Specification{
OnboardingServiceImpl service =new OnboardingServiceImpl()
OnboardingController controller
ResponseEntity response
#Unroll
def "HTTP response #statusCode when creating service model"() {
given:
if (exception) {
service = Stub() {
createServiceModel(_) >> { throw exception }
}
}
controller= new OnboardingController(onboardingService: service)
when:
response=controller.createServiceModel("test", Mock(MultipartFile))
then:
response.statusCode == statusCode
where:
exception | statusCode
null | OK
new MalformedContentException() | BAD_REQUEST
new ServiceModelNameAlreadyExistsException() | CONFLICT
new ServiceUnavailableException() | SERVICE_UNAVAILABLE
}
}
My service class is as follows:
package com.service.onboarding.business;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.service.onboarding.business.api.OnboardingService;
import com.service.onboarding.business.servicemanagement.ServiceModelRepository;
import com.service.onboarding.domain.exception.MalformedContentException;
import com.service.onboarding.domain.exception.ServiceModelDoesNotExistException;
import com.service.onboarding.domain.exception.ServiceModelInUseException;
import com.service.onboarding.domain.exception.ServiceModelNameAlreadyExistsException;
import com.onboarding.domain.exception.ServiceUnavailableException;
import com.service.onboarding.domain.requestdata.ServiceModelPaginationFilter;
import com.service.onboarding.domain.requestdata.ServiceModelRequestData;
import com.service.onboarding.domain.resource.Greeting;
import com.service.onboarding.domain.resource.ServiceModel;
import com.service.onboarding.domain.resource.ServiceModelDetail;
import com.service.onboarding.domain.responsedata.PaginatedServiceResponseData;
/*
* Sample service to demonstrate what the API would use to get things done
*/
#Service
public class OnboardingServiceImpl implements OnboardingService {
private final AtomicLong counter = new AtomicLong();
private static final String TEMPLATE = "Hello, %s!";
private static final Logger LOG = LoggerFactory.getLogger(OnboardingServiceImpl.class);
#Autowired
private ServiceModelRepository serviceModelRepository;
public OnboardingServiceImpl() {
}
#Override
public Greeting getPersonalGreeting(final String name) {
return new Greeting(counter.incrementAndGet(),
String.format(TEMPLATE, name));
}
#Override
public ServiceModelDetail createServiceModel(final ServiceModelRequestData serviceModelRequestData) throws MalformedContentException, ServiceModelNameAlreadyExistsException, ServiceUnavailableException {
return serviceModelRepository.create(serviceModelRequestData);
}
Your test should look like this:
package de.scrum_master.stackoverflow
import org.springframework.http.ResponseEntity
import org.springframework.web.multipart.MultipartFile
import spock.lang.Specification
import spock.lang.Unroll
import static org.springframework.http.HttpStatus.*
class OnboardingControllerTest extends Specification {
OnboardingService service = new OnboardingService()
OnboardingController controller
ResponseEntity response
#Unroll
def "HTTP response #statusCode when creating service model"() {
given:
if (exception) {
service = Stub() {
createServiceModel(_) >> { throw exception }
}
}
controller = new OnboardingController(onboardingService: service)
when:
response = controller.createServiceModel("test", Mock(MultipartFile))
then:
response.statusCode == statusCode
where:
exception | statusCode
null | OK
new MalformedContentException() | BAD_REQUEST
new ServiceModelNameAlreadyExistsException() | CONFLICT
new ServiceUnavailableException() | SERVICE_UNAVAILABLE
}
}
The console log (I switched to Java logging when replicating your use case) would be:
Mär 10, 2018 12:51:50 PM de.scrum_master.stackoverflow.OnboardingController createServiceModel
INFORMATION: Malformed Content: de.scrum_master.stackoverflow.MalformedContentException
Mär 10, 2018 12:51:50 PM de.scrum_master.stackoverflow.OnboardingController createServiceModel
INFORMATION: Service Model Name Already Exists: de.scrum_master.stackoverflow.ServiceModelNameAlreadyExistsException
Mär 10, 2018 12:51:50 PM de.scrum_master.stackoverflow.OnboardingController createServiceModel
INFORMATION: Service Unavailable currently: de.scrum_master.stackoverflow.ServiceUnavailableException
In my IDE (IntelliJ IDEA) the test result looks like this:
P.S.:
I know you are new to SO. So this was your free shot. Next time please provide an MCVE, i.e. a minimal, compilable and executable example, not just a code snippet without package name, imports and test class. You want help with Spock, so please write a Spock specification (test class), show it to us and explain your problem with it. That way we do not need to recreate your situation from scratch but can just concentrate on fixing your test and solving your problem.
You were lucky I just felt a bit bored, waiting for a guest to arrive, otherwise I would not have done that. Saying "I have nothing, please do everything for me" only shows that you are lazy. If you want help, make it easy for others to help and show some respect towards their time budget. They are doing it for free!
I have been struggling with getting this test to work for awhile, the relevant code executes fine in production my assumption is that it has some additional configuration, lots of searching seems to be related specifically to email handling and additional libraries, I don't want to include anything else, what am I missing to link DataHandler to a relevant way of handling "text/plain" ?
Expected result: DataHandler allows me to stream the input "Value" back into a result.
Reproduce issue with this code:
import java.io.IOException;
import java.io.InputStream;
import javax.activation.CommandInfo;
import javax.activation.CommandMap;
import javax.activation.DataHandler;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class DataHandlerTest {
#Before
public void setUp() throws Exception {
}
#After
public void tearDown() throws Exception {
}
#Test
public void test() throws IOException {
printDefaultCommandMap();
DataHandler dh = new DataHandler("Value", "text/plain");
System.out.println("DataHandler commands:");
printDataHandlerCommands(dh);
dh.setCommandMap(CommandMap.getDefaultCommandMap());
System.out.println("DataHandler commands:");
printDataHandlerCommands(dh);
final InputStream in = dh.getInputStream();
String result = new String(IOUtils.toByteArray(in));
System.out.println("Returned String: " + result);
}
private void printDataHandlerCommands(DataHandler dh) {
CommandInfo[] infos = dh.getAllCommands();
printCommands(infos);
}
private void printDefaultCommandMap() {
CommandMap currentMap = CommandMap.getDefaultCommandMap();
String[] mimeTypes = currentMap.getMimeTypes();
System.out.println("Found " + mimeTypes.length + " MIME types.");
for (String mimeType : mimeTypes) {
System.out.println("Commands for: " + mimeType);
printCommands(currentMap.getAllCommands(mimeType));
}
}
private void printCommands(CommandInfo[] infos) {
for (CommandInfo info : infos) {
System.out.println(" Command Class: " +info.getCommandClass());
System.out.println(" Command Name: " + info.getCommandName());
}
}
}
Exception:
javax.activation.UnsupportedDataTypeException: no object DCH for MIME
type text/plain at
javax.activation.DataHandler.getInputStream(DataHandler.java:249)
Help much appreciated, I hope this is a well formed question!
========================
Update 25th February
I have found if i know I stored a String in DataHandler, then I can cast the result to String and return the object that was stored, example:
#Test
public void testGetWithoutStream() throws IOException {
String inputString = "Value";
DataHandler dh = new DataHandler(inputString, "text/plain");
String rawResult = (String) dh.getContent();
assertEquals(inputString, rawResult);
}
But the code under test uses an InputStream, so my 'real' tests still fail when executed locally.
Continuing my investigation and still hoping for someone's assistance/guidance on this one...
Answering my own question for anyone's future reference.
All credit goes to: https://community.oracle.com/thread/1675030?start=0
The principle here is that you need to provide DataHandler a factory that contains a DataContentHandler that will behave as you would like it to for your MIME type, setting this is via a static method that seems to affect all DataHandler instances.
I declared a new class (SystemDataHandlerConfigurator), which has a single public method that creates my factory and provides it the static DataHandler.setDataContentHandlerFactory() function.
My tests now work correctly if I do this before they run:
SystemDataHandlerConfigurator configurator = new SystemDataHandlerConfigurator();
configurator.setupCustomDataContentHandlers();
SystemDataHandlerConfigurator
import java.io.IOException;
import javax.activation.*;
public class SystemDataHandlerConfigurator {
public void setupCustomDataContentHandlers() {
DataHandler.setDataContentHandlerFactory(new CustomDCHFactory());
}
private class CustomDCHFactory implements DataContentHandlerFactory {
#Override
public DataContentHandler createDataContentHandler(String mimeType) {
return new BinaryDataHandler();
}
}
private class BinaryDataHandler implements DataContentHandler {
/** Creates a new instance of BinaryDataHandler */
public BinaryDataHandler() {
}
/** This is the key, it just returns the data uninterpreted. */
public Object getContent(javax.activation.DataSource dataSource) throws java.io.IOException {
return dataSource.getInputStream();
}
public Object getTransferData(java.awt.datatransfer.DataFlavor dataFlavor,
javax.activation.DataSource dataSource)
throws java.awt.datatransfer.UnsupportedFlavorException,
java.io.IOException {
return null;
}
public java.awt.datatransfer.DataFlavor[] getTransferDataFlavors() {
return new java.awt.datatransfer.DataFlavor[0];
}
public void writeTo(Object obj, String mimeType, java.io.OutputStream outputStream)
throws java.io.IOException {
if (mimeType == "text/plain") {
byte[] stringByte = (byte[]) ((String) obj).getBytes("UTF-8");
outputStream.write(stringByte);
}
else {
throw new IOException("Unsupported Data Type: " + mimeType);
}
}
}
}
I need to make w WS call to handle HEAD request by myself, anyway it always get's response AFTER redirection (so finally I get always 200 status instead of ie. 301)
In documentation it's written that I should set ws.followRedirects=false in my application.conf, anyway it doesn't seem to work. I can see that Scala version is trying read this config, however I have a Java controller. Also can't switch to 2.1 now, where as I can see there is special setter for the issue.
Is there ANY workaround ?
You can call Scala from Java. The method wsHead encapsulates the Scala code and delivers only Objects from the Java Play API. Migrated to Play 2.1.0 you can refactor that method.
package controllers;
import play.api.libs.ws.Response;
import play.api.libs.ws.WS$;
import play.libs.F;
import play.libs.WS;
import play.mvc.*;
public class Application extends Controller {
public static Result index() {
final String url = "http://localhost:80";
final F.Promise<WS.Response> responsePromise = wsHead(url);
return async(responsePromise.map(new F.Function<WS.Response, Result>() {
#Override
public Result apply(WS.Response response) throws Throwable {
return ok("got status: " + response.getStatus());
}
}));
}
private static F.Promise<WS.Response> wsHead(String url) {
return new F.Promise(WS$.MODULE$.url(url).head()).map(new F.Function<Response, WS.Response>() {
#Override
public WS.Response apply(Response o) throws Throwable {
return new WS.Response(o.getAHCResponse());
}
});
}
}
You still need to add ws.followRedirects=false in your application.conf.