środa, 14 lutego 2018

Spring MVC - Redirect 404 when Optional.empty returned

Optional returned from controllers method

If you need to show 404 error page when no object found in your backend you can think of returning Optional from the controller's method and may expect Spring MVC takes care of exposing the value if present and throws 404 if empty.

Solution

The mechanism of controller advice comes to play. We can create a class that will be used to modify controller responses.

There are actually two features used:

  • @ExceptionHandler which is used for translation exceptions into 404 error response
  • ResponseBodyAdvice interface which cause body will be processed before been returned from controller endpoint.

Here you are piece of code that should gather above mentioned into one universal class

@ControllerAdvice
public class OptionalResponseControllerAdvice implements ResponseBodyAdvice {

 @Override
 public boolean supports(MethodParameter returnType, Class converterType) {
  return returnType.getParameterType().equals(Optional.class);
 }

 @Override
 public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
   Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
  if (returnType.getParameterType().equals(Optional.class)) {
   return ((Optional<?>) body).orElseThrow(() -> new NotFoundException("No object found: " + request.getURI()));
  }
  return body;
 }

 @ExceptionHandler(UnauthorizedException.class)
 public ResponseEntity<Map<String, Serializable>> handle(NotFoundException e) {
  return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage());
 }

}

wtorek, 13 lutego 2018

Angular 5 and underscore library

Are you missing the underscore library in your most recent Angular 5 project?

It is easier than you may think - the only you need to do is just add two dependencies to your package.json file.

Step 1. Install dependencies

You can do this with npm command.

npm install --save @types/underscore
and next
npm install --save underscore

Step 2. Use it

In order to use underscore library in your component or service class you have to import library in the following way:
import * as _ from "underscore";
That is basically all - now you can take all the goodies from underscore. For example, to fetch all unique key values from an array of key-value struct we can do this way:
public uniqueKeys(input: {[key: string]: string}[]): string[] {

   let keys = _
     .chain(input)
     .map(a => _.keys(a))
     .flatten()
     .uniq(false)
     .value()

piątek, 12 stycznia 2018

HttpClient - ssl - unable to find valid certification path to requested target

The javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target usually stands for issues with accepting/validating SSL/TLS certificate given by web server. ClientHandshaker class is responsible for handshaking from the client side. It shares common logic such control flow and key generation with its counterpart ServerHandshaker though common parent class called Handshaker.
void processMessage(byte type, int messageLen) throws IOException {
 ...
 switch (type) {
 ...
 case HandshakeMessage.ht_certificate:
       if (keyExchange == K_DH_ANON || keyExchange == K_ECDH_ANON
                    || keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
                fatalSE(Alerts.alert_unexpected_message,
                    "unexpected server cert chain");
                // NOTREACHED
            }
            this.serverCertificate(new CertificateMsg(input));
            serverKey =
                session.getPeerCertificates()[0].getPublicKey();
            break;
Let's go briefly to the details 1. Creating CerificateMsg just takes input as a HandshakeInStream, reads first 24 bytes as a chainLenght, so can read the cert as a byte array and finally instantiates X.509 certificate, as below
cf = CertificateFactory.getInstance("X.509");
cf.generateCertificate(new ByteArrayInputStream(cert)
2. serverCertificate method will deletegate cerificate validation to the Trust Manager taken from sslContext. To solve the error the sslcontext have to be feeded with TrustStrategy that accepts self-sighed cerificates as trusted. Apache Http Client comes with org.apache.http.conn.ssl.TrustSelfSignedStrategy to do so.
HttpClients.custom()
                .setSSLSocketFactory(new SSLConnectionSocketFactory(SSLContextBuilder.create()
      .loadTrustMaterial(TrustSelfSignedStrategy.INSTANCE)
      .build(), NoopHostnameVerifier.INSTANCE))
                .build();

wtorek, 9 stycznia 2018

Java - how to encode url right

Surprisingly its not an easy thing to encode URL once one wanted to make a request with Apache HttpClient. since most obvious URLEncode seems does not work well, though. URI baseUri = new URI("http://localhost:8090"); baseUri.getScheme(); URI path = new URI("http", null, "localhost", 8090, url, null, null);

poniedziałek, 1 stycznia 2018

Bash - how to do string split

STR=A.B.C && STR2=${STR%.*} && echo ${STR2%.*} && echo ${STR2#*.} && STR4=${STR#*.} && echo ${STR4#*.}
DELIMITER='.' && STR=A.B.C && echo ${STR%${DELIMITER}*}
for i in $(echo A.B.C | sed -e 's/\./ /g'); do echo $i; done

bash - how to check if string starts with specific prefix

Let's assume we want to process only files that start with specific string (eg. 2018). Our script is listening to every new file appeared in given directory, so let's assume we cannot do this at the os level directly. Our script is invoking the following command:
$ convert.sh /path/to/2018_file.pdf 
To process all files begins with 2018 we can do this way:
for i in `ls`; do [[ $i == 2018* ]] && echo $i; done
Or, if we'd like to process all but 2018 files we can do this way:
for i in `ls`; do [[ $i != 2018* ]] && echo $i; done
Or even more general with help of regexp we can do
for i in `ls`; do [[ $i =~ ^2018 ]] && echo $i; done
Happy New Year!!

środa, 13 grudnia 2017

bash - how to concatenate array with given delimiter

Let's declare array
 a=(aa bb cc) 
Now we can display the content with
$echo ${a[@]}
aa bb cc
First, give some naive solutions a try
$for el in ${a[@]}; do echo -n ,$el; done
,aa,bb,cc
$printf ",%s" ${a[@]}
,aa,bb,cc
Both work well, right? Hmm.. almost.

The last thing to do is get rid of the first comma

$for ab in ${a[@]}; do echo -n ,${ab}; done | cut -c2-
aa,bb,cc