assert output response sling servlet filter - java

I am trying to assert output of the below transformed response from sling servlet filter. I am not able to get hold of output response and not able to assert.
import com.day.cq.wcm.api.Page;
import com.safeway.app.rxwa.pharmacy.utils.HttpServletResponseCopier;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.engine.EngineConstants;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/**
* This filter rewrites link for the Content Fragment list model exporter
*/
#Component(service = Filter.class,
immediate = true,
configurationPolicy = ConfigurationPolicy.REQUIRE,
property = {
EngineConstants.SLING_FILTER_SCOPE + "=" + EngineConstants.FILTER_SCOPE_REQUEST,
EngineConstants.SLING_FILTER_METHODS + "=GET",
EngineConstants.SLING_FILTER_PATTERN + "=/content/experience-fragments/rxwa/.*",
EngineConstants.SLING_FILTER_SELECTORS + "=model",
EngineConstants.SLING_FILTER_EXTENSIONS + "=json"})
#Designate(ocd = ContentJsonLinkRewriterFilter.Config.class)
public class ContentJsonLinkRewriterFilter implements Filter {
private static final Logger logger =
LoggerFactory.getLogger(ContentJsonLinkRewriterFilter.class);
private Config config;
private List<String> resourceTypes;
#Reference
private ResourceResolverFactory resolverFactory;
#Activate
public void activate(Config config) {
this.config = config;
this.resourceTypes = Arrays.asList(config.resourceTypes());
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// no-op
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
String resultString = "{}";
// add author check
if (!(response instanceof SlingHttpServletResponse) || !(request instanceof SlingHttpServletRequest)) {
throw new IllegalStateException("Filter not properly registered as Sling Servlet Filter");
}
if (!config.enabled()) {
logger.debug("Filter disabled");
filterChain.doFilter(request, response);
return;
}
SlingHttpServletRequest slingHttpServletRequest = (SlingHttpServletRequest) request;
Resource currentResource = slingHttpServletRequest.getResource();
String currentResourceType = currentResource.getResourceType();
if(currentResource.isResourceType("cq:Page")) {
Page page = slingHttpServletRequest.getResource().adaptTo(Page.class);
currentResourceType = page.getContentResource().getResourceType();
}
String finalProcessResourceType = currentResourceType;
if (resourceTypes.stream().noneMatch(resourceType -> StringUtils.startsWith(finalProcessResourceType, resourceType))) {
logger.debug("Current resource path {} is not configured to be evaluated", currentResourceType);
filterChain.doFilter(request, response);
return;
}
// Wrap Response Class before servlet gets called
HttpServletResponseCopier responseCopier = new HttpServletResponseCopier((SlingHttpServletResponse) response);
filterChain.doFilter(request, responseCopier);
// externalize links after the servlet finishes
responseCopier.flushBuffer();
//read original response
byte[] responseBytes = responseCopier.getCopy();
String responseString = new String(responseBytes, responseCopier.getCharacterEncoding());
if (StringUtils.isNotEmpty(responseString)) {
//replace all links
resultString = responseString.replaceAll(StringUtils.substring(slingHttpServletRequest.getRequestURI(),0, slingHttpServletRequest.getRequestURI().lastIndexOf("/")), "");
}
responseCopier.resetBuffer();
responseCopier.getOutputStream().write(resultString.getBytes());
responseCopier.setContentType("application/json");
responseCopier.setCharacterEncoding("utf-8");
}
#Override
public void destroy() {
// no-op
}
#ObjectClassDefinition(name = "Content Fragment List Link Rewriter Filter",
description = "Configuration for filter to extend Content Fragment List functionality to rewrite links")
public #interface Config {
#AttributeDefinition(name = "Enabled",
description = "If this filter should not be active, rather try to delete this config. " + "Only in cases " +
"where this cannot be easily accomplished uncheck this option to disable the filter.") boolean enabled() default false;
#AttributeDefinition(name = "Resource Types",
description = "Resource Types to be evaluated by the filter.") String[] resourceTypes();
}
}
Unit test I tried
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import com.safeway.app.rxwa.pharmacy.utils.HttpServletResponseCopier;
import io.wcm.testing.mock.aem.junit.AemContext;
import org.apache.commons.io.IOUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.testing.mock.osgi.MapUtil;
import org.apache.sling.testing.mock.sling.loader.ContentLoader;
import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import com.day.cq.commons.jcr.JcrConstants;
import com.day.cq.wcm.api.components.ComponentContext;
import com.day.cq.wcm.api.designer.Design;
import com.day.cq.wcm.api.designer.Designer;
import com.google.common.collect.Sets;
import org.mockito.junit.MockitoJUnitRunner;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
#RunWith(MockitoJUnitRunner.class)
public class ContentJsonLinkRewriterFilterTest {
protected static final String CONTENT_ROOT = "/content/experience-fragments/rxwa";
public Map<String, Object> props = new HashMap<>();
#Rule
public AemContext context = new AemContext();
#Mock
FilterChain chain;
public ContentJsonLinkRewriterFilter filter;
#Before
public void setUp() {
context.load().json("/test-page-content.json", "/content/experience-
fragments/rxwa");
props.clear();
props.put("enabled", "true");
props.put("resourceTypes", new String[] {"rxwa-
pharmacy/components/structure/xfpage"});
ContentJsonLinkRewriterFilter aei = context.registerInjectActivateService(new
ContentJsonLinkRewriterFilter(), props);
filter = Mockito.spy(aei);
}
#Test
public void doFilterCall() throws ServletException, IOException {
context.requestPathInfo().setResourcePath("/content/experience-fragments/rxwa/templated-
page");
context.requestPathInfo().setSelectorString("model");
context.requestPathInfo().setExtension("json");
context.request().setMethod("GET");
context.response().setCharacterEncoding("UTF-8");
context.currentPage("/content/experience-fragments/rxwa/templated-page");
Mockito.doAnswer(invocation -> {
HttpServletResponseWrapper httpServletResponseWrapper =
(HttpServletResponseWrapper) invocation.getArguments()[1];
String testHtmlContent = IOUtils.toString(
ContentLoader.class.getResourceAsStream("/test-page-content.json"),
StandardCharsets.UTF_8
);
httpServletResponseWrapper.getWriter()
.write(testHtmlContent);
httpServletResponseWrapper.getWriter().flush();
return null;
}).when(chain).doFilter(Mockito.any(), Mockito.any());
filter.doFilter(context.request(), context.response(), chain);
Mockito.verify(chain).doFilter(Mockito.any(), Mockito.any());
String testHtmlContent2 = IOUtils.toString(
ContentLoader.class.getResourceAsStream("/test-page-content.json"),
StandardCharsets.UTF_8
);
}
}

Related

Unit testing - RestTemplate mock keeps retuning null

So Im writing unit test a class that does bankId authentication and the unit test looks like this.
package se.kt.client;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.HttpEntity;
import se.kt.common.vo.PublicApplicationForm;
import se.kt.models.BankIdAuthRequest;
import se.kt.models.BankIdAuthResponse;
import se.kt.models.BankIdCollectResponse;
import static org.mockito.ArgumentMatchers.any;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
#RunWith(MockitoJUnitRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class BankIdClientTest {
private final RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
#InjectMocks
private BankIdClient bankIdClient;
#BeforeEach
public void setUp() {
}
#Test
public void testBankIdAuthentication_success() throws InterruptedException {
PublicApplicationForm form = new PublicApplicationForm();
form.setSsn("123456-7890");
form.setIp_address("123.123.123.123");
BankIdAuthRequest authRequest = bankIdClient.authRequestFromApplicationForm(form, "123");
BankIdAuthResponse authResponse = new BankIdAuthResponse();
authResponse.setOrderRef("123456");
BankIdCollectResponse collectResponse = new BankIdCollectResponse();
collectResponse.setStatus("completed");
Mockito.when(restTemplate.postForEntity(anyString(), any(HttpEntity.class), any()))
.thenReturn(ResponseEntity.ok(authResponse));
Mockito.when(restTemplate.getForEntity(anyString(), any()))
.thenReturn(ResponseEntity.ok(collectResponse));
assertTrue(bankIdClient.bankIdAuthentication(authRequest));
}
}
And the class Im testing looks like this:
package se.kt.client;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import se.kt.common.domain.AbstractApplicationForm;
import se.kt.common.vo.PublicApplicationForm;
import se.kt.models.BankIdAuthRequest;
import se.kt.models.BankIdAuthResponse;
import se.kt.models.BankIdCollectResponse;
import javax.validation.constraints.AssertFalse;
import javax.validation.constraints.AssertTrue;
import java.util.Objects;
#Component
public class BankIdClient {
private static final Logger log = LoggerFactory.getLogger(BankIdClient.class);
private final RestTemplate customRestTemplate;
private static final String CONTENT_TYPE = "Content-Type";
#Value("${BankId.AuthUrl}")
private String bankIdAuthUrl;
#Value("${BankId.CollectUrl}")
private String bankIdCollectUrl;
#Value("${BankId.SecretKey}")
private String bankIdSecretKey;
public BankIdClient(RestTemplate customRestTemplate) {
this.customRestTemplate = customRestTemplate;
}
public BankIdAuthRequest authRequestFromApplicationForm(PublicApplicationForm form, String jobId) {
BankIdAuthRequest bankIdAuthRequest = new BankIdAuthRequest();
bankIdAuthRequest.setPno(form.getSsn());
bankIdAuthRequest.setIpAddress(form.getIp_address());
bankIdAuthRequest.setRefID(jobId);
bankIdAuthRequest.setSecretKey(bankIdSecretKey);
bankIdAuthRequest.setAvsikt("Kt application");
return bankIdAuthRequest;
}
public boolean bankIdAuthentication(BankIdAuthRequest bankIdAuthRequest) throws InterruptedException {
//Setup header and body for request.
HttpHeaders headers = new HttpHeaders();
headers.add(CONTENT_TYPE, MediaType.APPLICATION_JSON.toString());
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
try {
String bankIdAuthFormJson = ow.writeValueAsString(bankIdAuthRequest);
HttpEntity<String> httpEntity = new HttpEntity<>(bankIdAuthFormJson, headers);
ResponseEntity<BankIdAuthResponse> authResponse = customRestTemplate.postForEntity(bankIdAuthUrl, httpEntity, BankIdAuthResponse.class);
bankIdCollectUrl += Objects.requireNonNull(authResponse.getBody()).getOrderRef();
ResponseEntity<BankIdCollectResponse> collectResponse;
do {
collectResponse = customRestTemplate.getForEntity(bankIdCollectUrl, BankIdCollectResponse.class);
Thread.sleep(1500);
if (Objects.requireNonNull(collectResponse.getBody()).getStatus().equals("completed"))
return true;
if (Objects.requireNonNull(collectResponse.getBody()).getStatus().equals("failed"))
return false;
} while (Objects.requireNonNull(collectResponse.getBody()).getStatus().equals("progress"));
} catch (JsonProcessingException e) {
log.info(e.getMessage());
} catch (NullPointerException e) {
log.info(e.toString());
log.info("BankId API not responding correctly. Check server connection");
}
return false;
}
public void cancelBankIdAuthentication(#Value("${BankId.CancelUrl}") String bankIdCancelUrl) {
customRestTemplate.postForEntity(bankIdCancelUrl, null, String.class);
}
}
Now for some reson this line:
ResponseEntity<BankIdAuthResponse> authResponse = customRestTemplate.postForEntity(bankIdAuthUrl, httpEntity, BankIdAuthResponse.class);
keeps producing the result authResponse = null indicating that
Mockito.when(restTemplate.postForEntity(anyString(), any(HttpEntity.class), any()))
.thenReturn(ResponseEntity.ok(authResponse));
is not working. Now I have been playing around with this for over 3h and i still get the same result. What could i be doing wrong?
#InjectMocks only works with #Mock-annotated fields, not with fields which get assigned a manually created mock. Therefore you need to change:
private final RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
#InjectMocks
private BankIdClient bankIdClient;
to
#Mock
private RestTemplate restTemplate;
#InjectMocks
private BankIdClient bankIdClient;
I also recommend reading Why is my class not calling my mocked methods in unit test? which provides additional insights and points out some common mistakes when using Mockito or mocks in general.

How to correctly implement CORS in WebFlux?

I want to create a simple Spring Boot/Webflux server to serve as REST API. I'm trying to test it currently locally. The Webflux server is running on port 8080 and I have another server serving the html (React.js) running on port 3000. I want to make a CORS request from the website to the server. To that end I created a Java class with a method addCorsMappings and added #Configuration annotation. I was wondering if adding an annotation magically make Spring aware of the annotated class but according to this article I also need to add org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.mypackage.CORSHandler property in spring.factories file which I did. However I still see that addCorsMappings is not even called (I don't see log message). Being new to Spring Boot is there any other configuration I'm missing?
This is my main class:
package com.mypackage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import reactor.ipc.netty.http.server.HttpServer;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RequestPredicates.contentType;
import static org.springframework.web.reactive.function.server.RequestPredicates.method;
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.nest;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;
public class Server {
private static final Logger log = LogManager.getLogger(Server.class);
public static final String HOST = "localhost";
public static final int PORT = 8080;
public static void main(String[] args) throws Exception {
Server server = new Server();
server.startReactorServer();
System.out.println("Press ENTER to exit.");
System.in.read();
}
public RouterFunction<ServerResponse> routingFunction() {
PersonRepository repository = new DummyPersonRepository();
PersonHandler handler = new PersonHandler(repository);
return nest(path("/person"),
nest(accept(APPLICATION_JSON),
route(GET("/{id}"), handler::getPerson)
.andRoute(method(HttpMethod.GET), handler::listPeople)
).andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::createPerson));
}
public void startReactorServer() {
RouterFunction<ServerResponse> route = routingFunction().filter((request, next) -> {
log.warn(request.path());
if (request.path().contains("person")) {
log.warn("calling next()");
return next.handle(request);
} else {
return ServerResponse.status(UNAUTHORIZED).build();
}
});
HttpHandler httpHandler = toHttpHandler(route);
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
HttpServer server = HttpServer.create(HOST, PORT);
server.newHandler(adapter).block();
}
}
and this is my CORSHandler class:
package com.mypackage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.reactive.config.CorsRegistry;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
#Configuration
public class CORSHandler implements WebFluxConfigurer {
private static final Logger log = LogManager.getLogger(CORSHandler.class);
#Override
public void addCorsMappings(CorsRegistry registry) {
log.warn("from addCorsMappings!!");
registry.addMapping("*")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("Content-Type", "Access-Control-Allow-Headers", "Authorization",
"X-Requested-With", "mode")
.allowCredentials(true);
}
}
The solution I currently found is that The class which contains configuration methods needs to be given as a parameter to AnnotationConfigApplicationContext context. The context needs to be given as a parameter to WebHttpHandlerBuilder.webHandler(RouterFunctions.toWebHandler(route)).applicationContext(context). So the main class would look like this:
package com.mypackage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
import reactor.ipc.netty.http.server.HttpServer;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RequestPredicates.contentType;
import static org.springframework.web.reactive.function.server.RequestPredicates.method;
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.nest;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;
#SpringBootApplication
public class Server {
private static final Logger log = LogManager.getLogger(Server.class);
public static final String HOST = "localhost";
public static final int PORT = 8080;
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(CorsConfiguration.class);
Server server = new Server();
server.startReactorServer(ctx);
System.out.println("Press ENTER to exit.");
System.in.read();
}
public RouterFunction<ServerResponse> routingFunction() {
PersonRepository repository = new DummyPersonRepository();
PersonHandler handler = new PersonHandler(repository);
return nest(path("/person"),
nest(accept(APPLICATION_JSON),
route(GET("/{id}"), handler::getPerson)
.andRoute(method(HttpMethod.GET), handler::listPeople)
).andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::createPerson));
}
public void startReactorServer(AnnotationConfigApplicationContext ctx) {
RouterFunction<ServerResponse> route = this.routingFunction().filter((request, next) -> {
log.warn(request.path());
if (request.path().contains("person")) {
log.warn("calling next()");
return next.handle(request);
} else {
return ServerResponse.status(UNAUTHORIZED).build();
}
});
HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(RouterFunctions.toWebHandler(route))
.applicationContext(ctx).build();
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
HttpServer server = HttpServer.create(HOST, PORT);
server.newHandler(adapter).block();
}
}
and CorsConfiguration class would look like this:
package com.mypackage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
#Configuration
#EnableWebFlux
public class CorsConfiguration {
private static final Logger log = LogManager.getLogger(CorsConfiguration.class);
private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN, mode";
private static final String ALLOWED_METHODS = "GET, PUT, POST, DELETE, OPTIONS";
private static final String ALLOWED_ORIGIN = "*";
private static final String MAX_AGE = "3600";
#Bean
public WebFilter corsFilter() {
log.warn("from CorsConfiguration!!!");
return (ServerWebExchange ctx, WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
log.warn("after ServerHttpRequest");
if (CorsUtils.isCorsRequest(request)) {
log.warn("inside isCorsRequest");
ServerHttpResponse response = ctx.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter(ctx);
};
}
}
In this code corsFilter is called and sets the CORS headers but routing doesn't work however (404 status is returned).

#Autowired get null value

In Login class #Autowired is not null but when I try to use postman call Logout class #Autowired get null. I copy code from Login to Logout class just change variable name all code is same pattern I don't know what happening
package xxx.api.login
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import xxx.api.domain.logout.LoginRequest;
import xxx.api.domain.logout.LoginResponse;
import xxx.converter.FieldValidation;
import xxx.dto.log.MessageLog;
import xxx.logging.LogFactory;
#Component
public class LoginClient {
#Autowired
FieldValidation fieldValidation;
public LoginResponse login(LoginRequest loginRequest) throws Exception {
ObjectMapper mapper = new ObjectMapper();
final String url = "http://localhost:xxx/xxx/login";
LoginResponse responseObject = null;
try {
String requestData = mapper.writeValueAsString(loginRequest);
responseObject = login(url, requestData);
fieldValidation.validateResponse(responseObject, "login");
// 'fieldValidation' not null
This is my Login class. Return result as I expect.
package xxx.api.logout;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import xxx.api.domain.logout.LogoutRequest;
import xxx.api.domain.logout.LogoutResponse;
import xxx.converter.FieldValidation;
import xxx.dto.log.MessageLog;
import xxx.logging.LogFactory;
#Component
public class LogoutClient {
#Autowired
FieldValidation fieldValidation;
public LogoutResponse logout(LogoutRequest logoutRequest) throws Exception {
ObjectMapper mapper = new ObjectMapper();
final String url = "http://localhost:xxx/xxx/logout";
LogoutResponse responseObject = null;
try {
String requestData = mapper.writeValueAsString(logoutRequest);
responseObject = logout(url, requestData);
fieldValidation.validateResponse(responseObject, "logout");
// 'fieldValidation' is null then throws nullPointerException
This is my Logout class
package xxx.api.logout;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import xxx.api.domain.logout.LogoutRequest;
import xxx.api.domain.logout.LogoutResponse;
import xxx.dto.log.MessageLog;
import xxx.exception.common.ErrorException;
import xxx.api.logout.LogoutClient;
import xxx.converter.FieldValidation;
#RestController
#RequestMapping(path = "/xxx")
public class LogoutServer {
#Autowired
FieldValidation fieldValidation;
#Autowired
WSLogFactory wsLog;
#PostMapping(value = "/logout", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<?> logout(#RequestHeader(value = "requestId") String requestId,
#RequestBody(required = true) LogoutRequest logoutRequest) throws ErrorException, Exception {
writeLogRequest(logoutRequest, logoutRequest.getClientIP(), "Request", "/xxx/logout");
fieldValidation.validateRequest(logoutRequest, "logout");
try {
LogoutClient logoutClient = new LogoutClient();
LogoutResponse response = logoutClient.logout(logoutRequest);
return new ResponseEntity<LogoutResponse>(response, HttpStatus.OK);
} catch (Exception e) {
throw e;
}
}
This is Logout Controller
#org.springframework.context.annotation.Configuration
#PropertySource("file:${layout.properties_file}")
public class FieldValidation {
// do somethings
}
This is my FieldValidation class.
{
"timestamp": 1550490230074,
"status": 500,
"error": "Internal Server Error",
"exception": "java.lang.NullPointerException",
"message": "No message available",
"path": "/umm/logout"
}
This is return when I call my Logout class.
This is my project structure
xxx.api.login <<< LoginClient.java
xxx.api.logout <<< LogoutClient.java
xxx.converter <<< FieldValidation.java
This is my main program
package xxx;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I try to replace #Component to #Configuration but still doesn't works.
I don't need 'fieldValidation' in Logout class or another class be a null value.
package xxx.converter;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Year;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import org.springframework.context.annotation.Configuration;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.validator.routines.BigDecimalValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import com.fasterxml.jackson.databind.ObjectMapper;
import xxx.exception.common.ErrorException;
#Configuration
#PropertySource("file:${layout.properties_file}")
public class FieldValidation {
public void validateObject(Object objResponse, String config) throws Exception {
try {
List<Configuration> confs = objectMapper.readValue(config,
objectMapper.getTypeFactory().constructCollectionType(List.class, Configuration.class));
for (int i = 0; i < confs.size(); i++) {
Configuration configuration = confs.get(i);
Object objValue = getValue(configuration.getFieldName(), objResponse);
Validation validation = new Validation();
BeanUtils.copyProperties(validation, configuration);
isValid(objValue, validation);
if (configuration.getType().equalsIgnoreCase("object")) {
List<Validation> validations = configuration.getValidation();
Class<?> act = Class.forName(configuration.getClassName());
Object objectConfig = act.cast(objValue);
validateObject(objectConfig, validations);
}
}
} catch (Exception e) {
throw e;
}
}
This is full import of FieldValidation class and replace #Configuration and I get this error.
configuration.getFieldName() << error The method is undefined for type Configuration
configuration.getType() << error The method is undefined for type Configuration
configuration.getValidation() << error The method is undefined for type Configuration
configuration.getClassName() << error The method is undefined for type Configuration

How to set response header for digital asset in AEM CQ6.1?

I have a request that if a user directly accesses a .pdf asset(for example, http://localhost:4505/content/dam/company/us/en/962059.pdf) from AEM CQ 6.1, I need to send a custom http respone header. This is what I wrote. This is only works if I open a .html page. But it doesn't work if I open a .pdf in browser. So what did I do wrong?
Thanks
package com.mycompany.wcm.filter;
import org.apache.felix.scr.annotations.*;
import org.apache.felix.scr.annotations.sling.SlingFilter;
import org.apache.felix.scr.annotations.sling.SlingFilterScope;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.*;
import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.api.scripting.SlingScriptHelper;
import org.apache.sling.runmode.RunMode;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Session;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
#SlingFilter(
label = "Sample Filter",
description = "Sample Description",
metatype = true,
generateComponent = true, // True if you want to leverage activate/deactivate
generateService = true,
order = -501, // The smaller the number, the earlier in the Filter chain (can go negative);
scope = SlingFilterScope.REQUEST)
#Properties({
#Property(
label = "Vendor",
name = "service.vendor",
value = "SampleVendor",
propertyPrivate = true
)
})
public class AssetFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
final SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) response;
slingResponse.setHeader("myheader1","no-cache");
slingResponse.setHeader("myheader2","no-store");
chain.doFilter(request, response);
}
#Override
public void destroy() {
}
}
Just a update, initialy I thought the problem only happens to .pdf file, but this also happens to image file. So I created a regular JSP web application, and this code is working for regular web app. Is there something funny on AEM side?

java unit test mock HttpClient and webdav

Hello I have a class for doing webdav related operations such as creating a directory, Implementatiion can be seen below (the createDir method). The question is how to test it nicely, perhaps using EasyMock or a similar lib. Any ideas? thanks!
package foobar;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.jackrabbit.webdav.client.methods.DavMethod;
import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import mypackage.httpdclient.util.URLHandler;
public class WebDavImpl{
private static final String SEPARATOR = " ----- ";
private HttpClient httpClient;
public StorageSpaceClientImpl() {
httpClient = new HttpClient();
}
public String createDir(String dirName) {
String response = null;
String url = URLHandler.getInstance().getDirectoryUrl(dirName);
DavMethod mkcol = new MkColMethod(url);
try {
httpClient.executeMethod(mkcol);
response = mkcol.getStatusCode() + SEPARATOR + mkcol.getStatusText();
} catch (IOException ex) {
} finally {
mkcol.releaseConnection();
}
return response;
}
}

Categories