Trying to write very simple http message converter to add encryption around request & respose.
Implemented rest controller and messageConverter. writeInternal does get invoked during response. However readInternal does not get invoked when request is sent to the rest end point.
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.techm.bm.util.EncryptDecryptUtil;
#Component
public class MessageEncryptionConverter extends AbstractHttpMessageConverter<Object> {
#Autowired
private ObjectMapper objectMapper;
public MessageEncryptionConverter() {
super(MediaType.ALL);
}
#Override
protected boolean supports(Class<?> clazz) {
return true;
}
#Override
protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
return objectMapper.readValue(decrypt(inputMessage.getBody()), clazz);
}
#Override
protected void writeInternal(Object o, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
outputMessage.getBody().write(encrypt(objectMapper.writeValueAsBytes(o)));
}
The below code is for encryption and decryption of request and response body For overall Project to modify response body and request parameters. Please check this code is works for me
For Request Encryption refer readInternal
below is the front-end or postman request sending, you have to add encrypted request in Json formate
Ex.{data : "+++++++++++++YOUR_ENCRYPTED_STRING++++++++++"}
For Response Descryption refer writeInternal
sending back to your front-end or postman request response with encrypted string
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.techm.bm.util.EncryptDecryptUtil;
#Component
public class MessageEncryptionConverter extends AbstractHttpMessageConverter<Object> {
#Autowired
private ObjectMapper objectMapper;
public MessageEncryptionConverter() {
super(MediaType.ALL);
}
#Override
protected boolean supports(Class<?> clazz) {
return true;
}
#Override
protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
return objectMapper.readValue(decrypt(inputMessage.getBody()), clazz);
}
#Override
protected void writeInternal(Object o, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
outputMessage.getBody().write(encrypt(objectMapper.writeValueAsBytes(o)));
}
// Convert request to input stream for sending to the controller
private InputStream decrypt(InputStream inputStream) throws IOException {
//this is API request params
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try {
Reader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
} catch (UnsupportedEncodingException e) {
logger.error("UnsupportedEncodingException" + e.getMessage());
} catch (IOException e) {
logger.error("IOException" + e.getMessage());
} finally {
inputStream.close();
}
try {
JSONObject requestJsonObject = new JSONObject(writer.toString().replace("\n", ""));
// Add your decryption method the object data will get your encrypted string data and return with string of your JSON object
String decryptRequestString = EncryptionUtils.decryptText(requestJsonObject.getString("data"));
if (decryptRequestString != null) {
return new ByteArrayInputStream(decryptRequestString.getBytes(StandardCharsets.UTF_8));
} else {
return inputStream;
}
} catch (JSONException err) {
logger.error("Error" + err.toString());
} catch (NoSuchAlgorithmException | BadPaddingException | DigestException | InvalidKeyException
| InvalidAlgorithmParameterException | NoSuchPaddingException | IllegalBlockSizeException e) {
logger.info("NoSuchAlgorithmException | BadPaddingException | DigestException | InvalidKeyException | " +
"InvalidAlgorithmParameterException | NoSuchPaddingException | IllegalBlockSizeException:: " + e.getMessage());
}
return inputStream;
}
private byte[] encrypt(Object obj) throws JsonProcessingException {
// do your encryption here
try {
String stringFromObject = objectMapper.writeValueAsString(obj);
// Add your encryption method
String encrypt = EncryptionUtils.encryptText(stringFromObject);
return objectMapper.writeValueAsBytes(encrypt);
} catch (Exception e) {
logger.info("Error While Encrypt data :: " + e.getMessage());
return objectMapper.writeValueAsBytes(obj);
}
}
}
Reference code Spring Boot - Encrypt JSON data
Hope this code is working for you
It is invoking if the request has body and "supports" method return ture
Related
Both methods, "createToken" and "getAuthentication" return errors when being used in class "JWTAuthenticationFilter" and "JWTAuthorizationFilter". The errors are Non-static method 'getAuthentication(java.lang.String)' cannot be referenced from a static context
The problem is that I don't have a single static field in all my code, so I don't understand the error. I also can't just declare the methods as static because I need to use the variable "jwt_secret" and in my previous post someone explained why I shouldn't make it static:
"Spring will not inject (autowire) into static fields.; that wouldn't make any sense even if it could. Spring beans are instances of classes, but static fields are not associated to any one instance. There are some ugly workarounds but better would be to eliminate the use of static fields."
TokenUtils
package com.XX.ZZ.security;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.stereotype.Component;
import java.util.*;
#Component
public class TokenUtils {
#Autowired
#Value("${custom.data.jwt.secret}")
private final String jwt_secret;
public TokenUtils(String jwtSecret) {
jwt_secret = jwtSecret;
}
public String createToken(String name, String email){
long expirationTime = 86400 * 1000;
Date expirationDate = new Date(System.currentTimeMillis() + expirationTime);
Map<String, Object> extra = new HashMap<>();
extra.put("name", name);
return Jwts.builder()
.setSubject(email)
.setExpiration(expirationDate)
.addClaims(extra)
.signWith(Keys.hmacShaKeyFor(jwt_secret.getBytes()))
.compact();
}
public UsernamePasswordAuthenticationToken getAuthentication(String token){
try {
Claims claims = Jwts.parserBuilder()
.setSigningKey(jwt_secret.getBytes())
.build()
.parseClaimsJws(token)
.getBody();
String email = claims.getSubject();
return new UsernamePasswordAuthenticationToken(email, null, Collections.emptyList());
} catch (JwtException e){
return null;
}
}
}
JWTAuthorizationFilter, error in UsernamePasswordAuthenticationToken usernamePAT = TokenUtils.getAuthentication(token)
package com.XX.ZZ.security;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
#Component
public class JWTAuthorizationFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String bearerToken = request.getHeader("Authorization");
if(bearerToken != null && bearerToken.startsWith("Bearer ")){
String token = bearerToken.replace("Bearer ", "");
UsernamePasswordAuthenticationToken usernamePAT = TokenUtils.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(usernamePAT);
}
filterChain.doFilter(request, response);
}
}
JwtAuthenticationFilter, error in String token = TokenUtils.createToken
package com.XX.ZZ.security;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import java.io.IOException;
import java.util.Collections;
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
#Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
AuthCredentials authCredentials = new AuthCredentials();
try {
authCredentials = new ObjectMapper().readValue(request.getReader(), AuthCredentials.class);
} catch (IOException e){ }
UsernamePasswordAuthenticationToken usernamePAT = new UsernamePasswordAuthenticationToken(
authCredentials.getEmail(),
authCredentials.getPassword(),
Collections.emptyList()
);
return getAuthenticationManager().authenticate(usernamePAT);
}
#Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authResult) throws IOException, ServletException {
UserDetailsImpl userDetails = (UserDetailsImpl) authResult.getPrincipal();
String token = TokenUtils.createToken(userDetails.getName(), userDetails.getUsername());
response.addHeader("Authorization", "Bearer " + token);
response.getWriter().flush();
super.successfulAuthentication(request, response, chain, authResult);
}
}
By calling it as TokenUtils.getAuthentication(token) you are literally calling it as as if it is a static. You need an instance in JWTAuthenticationFilter:
TokenUtils tokenUtilsInstance = new TokenUtils("my secret");
tokenUtilsInstance.getAuthentication(token)
You probably need to drop the constructor TokenUtils(String jwtSecret). That will allow the following in JWTAuthenticationFilter. Much better Spring practice.
#Autowired
TokenUtils tokenUtilsInstance;
I would like to generate the token for login using springboot, The token is generating while checking using postman, but I am getting null in console
Authenticate controller
package com.demo.grocery.controller;
import com.demo.grocery.config.JwtUtils;
import com.demo.grocery.model.JwtRequest;
import com.demo.grocery.model.JwtResponse;
import com.demo.grocery.model.User;
import com.demo.grocery.service.impl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
#RestController
public class AuthenticateController {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private UserDetailsServiceImpl userDetailsServiceImpl;
#Autowired
private JwtUtils jwtUtils;
//generate token
#CrossOrigin("http://localhost:4200")
#PostMapping("/generate-token")
public ResponseEntity<?> generateToken(#RequestBody JwtRequest jwtRequest) throws Exception
{
try {
this.authenticate(jwtRequest.getUsername(), jwtRequest.getPassword());
} catch (UsernameNotFoundException e) {
// TODO: handle exception
e.printStackTrace();
throw new Exception("User Not Found");
}
////////////authenticate
UserDetails userDetails = this.userDetailsServiceImpl.loadUserByUsername(jwtRequest.getUsername());
String token = this.jwtUtils.generateToken(userDetails);
return ResponseEntity.ok(new JwtResponse(token));
}
private void authenticate(String username, String password) throws Exception
{
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
e.printStackTrace();
throw new Exception("USER DISABLED "+e.getMessage());
}
catch(BadCredentialsException e)
{
throw new Exception("Invalid Credentials "+e.getMessage());
}
}
//returns the details of current logged in user
#CrossOrigin("http://localhost:4200")
#GetMapping("/current-user")
public User getCurrentUser(Principal principal)
{
return (User) this.userDetailsServiceImpl.loadUserByUsername(principal.getName());
}
}
JwtAuthenticationFilter
package com.demo.grocery.config;
import com.demo.grocery.service.impl.UserDetailsServiceImpl;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
#Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
#Autowired
private UserDetailsServiceImpl userDetailsService;
#Autowired
private JwtUtils jwtUtil;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
System.out.println(requestTokenHeader);
String username = null;
String jwtToken = null;
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
// yes
jwtToken = requestTokenHeader.substring(7);
try {
username = this.jwtUtil.extractUsername(jwtToken);
} catch (ExpiredJwtException e) {
e.printStackTrace();
System.out.println("jwt token has expired..");
}
catch (Exception e) {
e.printStackTrace();
System.out.println("error");
}
}
else {
System.out.println("Invalid Token, Not Starts with bearer String");
}
//validate Token
if(username!=null && SecurityContextHolder.getContext().getAuthentication() == null)
{
final UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if(this.jwtUtil.validateToken(jwtToken, userDetails))
{
//token is valid
UsernamePasswordAuthenticationToken usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
usernamePasswordAuthentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthentication);
}
else
{
System.out.println("Token is not Valid");
}
}
filterChain.doFilter(request, response);
}
}
Service
package com.demo.grocery.service.impl;
import com.demo.grocery.model.User;
import com.demo.grocery.repository.UserRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserRepo userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = this.userRepository.findByUsername(username);
if (user == null) {
System.out.println("User Not Found");
throw new UsernameNotFoundException("No User Found!!");
}
return user;
}
}
Output in intelliji
Postman output
Look into the screenshots and help me to solve the issue. Why it is storing as null?
For your method to work you should pass your JWT in Postman using Authorization -> Type: Bearer Token.
As you can see in your console log, there's a message "Invalid Token, Not Starts with bearer String", which is printed from your JwtAuthenticationFilter when there's no Authorization header or it doesn't start with "Bearer".
At this point your user is not authenticated, so there's no Principal object in SecurityContextHolder when controller method is executed.
For these cases you should convert response to 401 UNAUTHORIZED status. For example, you can do it in your filter by writing straight to response.
But implementing your own security mechanism is considered a bad practice. I advise to use spring-security build-in JWT-support, which will automatically respond with 401 when there's no valid token found in Authorization header and will store additional info about missing or invalid token at response WWW-Authenticate header.
Take a look at spring-security official sample of jwt-secured resource-server.
I am unable to moock webclient
WebClientConfig.java
public #Bean("oauthWebClient") WebClient oauthWebClient() {
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create().option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000)
.doOnConnected(connection -> connection.addHandlerLast(new ReadTimeoutHandler(10))
.addHandlerLast(new WriteTimeoutHandler(10)))))
.filter(logOAuthResponse()).baseUrl(oauthTokenUrl)
.defaultHeaders(headers -> {
headers.setBasicAuth(secretHeaderValue);
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
})
.defaultUriVariables(oauthUriVariables)
.build();
}
serviceUti.java
package com.test.stats.volts.busops.utils;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientRequestException;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.test.stats.volts.busops.exception.VoltsDataAccessException;
import com.test.stats.volts.busops.exception.MtnDataAccessNotRespondingException;
import com.test.stats.volts.busops.exception.VoltsDataAcessException;
import com.test.stats.volts.busops.exception.UnableToGetOAuthTokenException;
#Component("voltsDataAccessServiceUtil")
public class ServiceUtil {
private static final Logger logger = LoggerFactory.getLogger(ServiceUtil.class);
#Autowired
#Qualifier("voltsDataAccessWebClient")
WebClient voltsDataAccessClient;
#Autowired
#Qualifier("oauthWebClient")
WebClient oauthClient;
#Value("${volts.dataaccess.end.point.save-meeting}")
private String saveMeetingEndPoint;
#Value("${volts.dataaccess.oauth.header-key.name}")
private String oauthHeaderKeyName;
#Value("${volts.dataccess.oauth.response.token.key-name}")
private String oauthResponseTokenKeyName;
#Value("#{${volts.dataaccess.api.endpoints.default.uri-variables}}")
private Map<String, String> voltsDataAccessUriVariables;
#Autowired
ObjectMapper mapper;
#Value("#{${volts.dataaccess.oauth.uri-variables}}")
private Map<String, String> oauthUriVariables;
#Value("${volts.dataaccess.oauth.scope}")
private String oauthScope;
#Value("${volts.dataaccess.oauth.grant_type}")
private String grantType;
#Value("${volts.dataaccess.oauth.secret.header-name}")
private String secretHeaderName;
#Value("${volts.dataaccess.oauth.secret.header-value}")
private String secretHeaderValue;
#Value("${volts.dataaccess.end.point.fetch-meeting}")
private String fetchMeetingEndPoint;
#Value("${volts.dataaccess.query.param.api-key-value}")
private String apiKey;
#Retryable(maxAttempts = 2)
public String postOAuthToken() throws VoltsDataAccessException {
try {
String respEntity = oauthClient.post()
.uri(uriBuilder -> uriBuilder.queryParam("scope", oauthScope).queryParam("grant_type", grantType)
.build())
.headers(headers -> headers.setBasicAuth(secretHeaderValue))
.retrieve()
.bodyToMono(String.class)
.block();
if (respEntity == null)
throw new UnableToGetOAuthTokenException(
"Exception while fetching OAUthToken as response from OAUth service is null resposne body");
try {
return mapper.readValue(respEntity, ObjectNode.class).get(oauthResponseTokenKeyName).asText();
} catch (JsonProcessingException e) {
logger.error("Exception while pasring token from Oauth ", e);
throw new UnableToGetOAuthTokenException(
"Exception while fetching OAUthToken as response from OAUth service is null resposne body");
}
} catch (WebClientRequestException e) {
logger.error("Request Exception to OAUth: message {}", e.getMessage(), e);
logger.error("", e);
throw new VoltsDataAccessException(e.getMessage(), HttpStatus.REQUEST_TIMEOUT.value());
}
catch (WebClientResponseException e) {
throw new VoltsDataAccessException(e.getMessage(), e.getRawStatusCode());
}
}
#Retryable(value = VoltsDataAcessException.class)
public ResponseEntity<VoltsResp> postSaveMeetingDetails(SaveVoltsReq voltsReq)
throws VoltsDataAcessException {
try {
ResponseEntity<VoltsResp> resp = voltsDataAccessClient.post()
.uri(saveMeetingEndPoint, uri -> uri.queryParam("apikey", apiKey).build())
.headers(headers -> headers.setBearerAuth(postOAuthToken()))
.contentType(MediaType.APPLICATION_JSON).bodyValue(voltsReq).retrieve()
.toEntity(VoltsResp.class).block();
return resp;
} catch (WebClientRequestException e) {
throw new VoltsDataAcessException(e.getMessage(), HttpStatus.REQUEST_TIMEOUT.value());
} catch (WebClientResponseException e) {
throw new VoltsDataAcessException(e.getMessage(), e.getRawStatusCode());
}
}
}
My test classs
WebClienrTests.java
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.reactive.function.client.WebClient;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.stats.volts.busops.config.WebClientConfig;
import com.test.stats.volts.busops.utils.ServiceUtil;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
#SpringBootTest(classes = { ServiceUtil.class, WebClientConfig.class,
ObjectMapper.class })
#RunWith(SpringRunner.class)
class ServiceUtilTests {
public static MockWebServer mockServer = new MockWebServer();
#MockBean
WebClientConfig webClientCondfig;
#Autowired
ServiceUtil serviceUtil;
#MockBean(name = "oauthWebClient")
WebClient oauthClient;
#MockBean(name = "voltsDataAccessWebClient")
WebClient voltsDataAccessWebClient;
#BeforeEach
void startMockServer() throws Exception {
mockServer.start(9090);
oauthClient = WebClient.create(mockServer.url("/").url().toString());
}
#AfterEach
void stopMockServer() throws Exception {
mockServer.shutdown();
}
#Test
void testPostOAuth() throws Exception {
mockServer.enqueue(new MockResponse().setResponseCode(200).setBody("OAuthToken"));
String expected = serviceUtil.postOAuthToken();
assertThat(expected).isNotNull().isEqualTo("OAuthToken");
}
}
When I run above test I get this error
java.lang.NullPointerException:
At postAuthToken() while setting headers .headers(headers -> headers.setBasicAuth(secretHeaderValue))
Please help on how to mock whole thing
I'am Ropi, i have an issue with my spring boot project test.
The issue is :
UnknownClassName.initializationError : NoClassDefFound UnknownClassName;
when i run the project it with skiped test proccess, it run well . and then i run the test it also run well..
but after i edit the test ( for example : i only add space on my test code), it give me an error.
and then when i edited my working code ( for example : i only add space on my coding work ), it give me illegal error.
My testing Code :
import com.emerio.rnd.otp.service.OtpService;
import org.hamcrest.core.IsNot;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.hamcrest.Matchers.*;
#RunWith(SpringRunner.class)
// #SpringBootTest
#WebFluxTest
public class OtpApplicationTests {
private Integer OTP1;
private Integer OTP2;
#Autowired
private WebTestClient webTestClient;
private OtpService otpService = new OtpService();
#Before
public void setup() throws Exception {
OTP1 = otpService.generateOTP("admin");
OTP2 = otpService.generateOTP("admin1");
}
// #WebFluxTest(OtpController.class)
#Test
public void generateOTPSuccess() throws Exception
{
webTestClient.get().uri("/generateotp/admin")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$.data.otp").isNotEmpty();
}
#Test
public void generateOTPUsernameNotExist() throws Exception
{
webTestClient.get().uri("/generateotp/null")
.exchange()
.expectStatus().isBadRequest();
}
// #Test
// public void generateNewOTP() throws Exception
// {
// webTestClient.get().uri("/generateotp/admin1")
// .exchange()
// .expectStatus().isOk()
// .expectBody()
// .jsonPath("$.[otp != "+OTP2+"]");
// }
#Test
public void validateOTPSuccess() throws Exception
{
webTestClient.get().uri("/validateotp/admin/"+OTP1.toString())
.exchange()
.expectStatus().isOk();
}
#Test
public void validateOTPfailed() throws Exception
{
webTestClient.get().uri("/validateotp/admin/981981")
.exchange()
.expectStatus().isBadRequest();
}
#Test
public void validateOTPWithChar() throws Exception
{
webTestClient.get().uri("/validateotp/admin/AS1213")
.exchange()
.expectStatus().isBadRequest();
}
#Test
public void validateOTPTimeOut() throws Exception
{
// Thread.sleep(300010);
webTestClient.get().uri("/validateotp/admin/981981")
.exchange()
.expectStatus().isBadRequest();
}
My Controller Working code
My Controller :
import com.emerio.rnd.otp.response.Response;
import com.emerio.rnd.otp.service.OtpService;
import com.google.gson.Gson;
import org.json.JSONObject;
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.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
#RestController
public class OtpController
{
private OtpService otpService = new OtpService();
private Response response = new Response();
#RequestMapping(method=RequestMethod.GET , value="/generateotp/{username}", produces=MediaType.APPLICATION_JSON_UTF8_VALUE)
public Mono<Object> generateOTP (#PathVariable String username)
{
try
{
if (username.equals("null"))
{
return Mono.just(new Throwable("error"));
} else
{
int otp = otpService.generateOTP(username);
JSONObject jObj = new JSONObject();
jObj.put("otp", otp);
return Mono.just(response.loaded(new Gson().fromJson(jObj.toString(), Object.class)));
}
} catch (Exception e)
{
return null;
}
}
#RequestMapping(method=RequestMethod.GET , value="/validateotp/{username}/{otp}", produces=MediaType.APPLICATION_JSON_UTF8_VALUE)
public Mono<Response> validateOTP (#PathVariable String username, #PathVariable String otp)
{
try
{
Integer otpCache = otpService.getOTP(username);
if (!otpCache.toString().equals(otp))
{
System.out.println("cache awal : " + otpCache);
System.out.println("cache : " + otp);
return Mono.just(response.loaded("otp not valid"));
} else
{
otpService.clearOTP(username);
return Mono.just(response.loaded("otp valid"));
}
} catch (Exception e)
{
return null;
}
}
My OTP Service :
package com.emerio.rnd.otp.service;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.springframework.stereotype.Service;
#Service
public class OtpService
{
private static final Integer EXPIRE_MINS = 5;
private LoadingCache<String, Integer> otpCache;
public OtpService()
{
super();
otpCache = CacheBuilder.newBuilder()
.expireAfterWrite(EXPIRE_MINS, TimeUnit.MINUTES).build(new CacheLoader<String,Integer>()
{
public Integer load (String key)
{
return 0;
}
});
}
public int generateOTP (String key)
{
Random random = new Random();
int otp = 100000 + random.nextInt(900000);
otpCache.put(key, otp);
return otp;
}
public int getOTP (String key)
{
try
{
return otpCache.get(key);
} catch (Exception e)
{
return 0;
}
}
public void clearOTP (String key)
{
otpCache.invalidate(key);
}
}
I am new to jfree chart I have the following code it runs without any error, however the browser shows me an empty page .. do not know where is the problem.
I am trying to create a bar chart using jfree chart in servlet and the data will be retrieved from oracle data base.
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.sql.*;
import java.util.*;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartUtilities;
public class BarChar extends HttpServlet {
#Override
public void init() {
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
System.out.println("JDBC driver loaded");
}
catch (ClassNotFoundException e) {
System.out.println(e.toString());
}
}
#Override
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
OutputStream out = response.getOutputStream();
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:XE","FATIMAH", "FATIMAH");
DefaultCategoryDataset bar = new DefaultCategoryDataset();
Statement stmt = conn.createStatement();
ResultSet r = stmt.executeQuery("select category,marks from chart_data");
while (r.next())
{
String category = r.getString("CATEGORY");
int marks = r.getInt("MARKS");
bar.addValue(marks,"Mark",category);
}
JFreeChart BarChartObject=ChartFactory.createBarChart("Subject Vs Marks Bar Chart","Subject","Marks",bar,PlotOrientation.VERTICAL,true,true,false);
response.setContentType("image/png");
ChartUtilities.writeChartAsPNG(out, BarChartObject, 400, 300);
}
catch (Exception e) {
System.err.println(e.toString());
}
finally {
out.close();
}
}
}