Saturday, January 31, 2015

Show registered servlet filters' information in Spring Boot

To show registered servlet filters' information in Spring Boot,

just see your INFO level logs in your console:

2015-02-01 14:52:15.204  INFO 1394 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2015-02-01 14:52:15.205  INFO 1394 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'springSecurityFilterChain' to: [/*]
2015-02-01 14:52:15.205  INFO 1394 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'mySiteMeshFilter' to urls: [/*]
2015-02-01 14:52:15.205  INFO 1394 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2015-02-01 14:52:15.205  INFO 1394 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]

As you can see, there is also information on a registered servlet.

If you use a version since 1.2.2.BUILD-SNAPSHOT,

you can see more detailed information on servlet filters in DEBUG level logs as follows:

2015-02-01 14:56:17.701 DEBUG 1427 --- [ost-startStop-1] o.s.b.c.e.ServletContextInitializerBeans : Added existing Filter initializer bean 'securityFilterChainRegistration'; order=0, resource=class path resource [org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfiguration.class]
2015-02-01 14:56:17.701 DEBUG 1427 --- [ost-startStop-1] o.s.b.c.e.ServletContextInitializerBeans : Added existing Filter initializer bean 'sitemeshFilter'; order=2147483647, resource=class path resource [samples/springboot/ServletFilterConfig.class]
2015-02-01 14:56:17.701 DEBUG 1427 --- [ost-startStop-1] o.s.b.c.e.ServletContextInitializerBeans : Added existing Servlet initializer bean 'dispatcherServletRegistration'; order=2147483647, resource=class path resource [org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration$DispatcherServletConfiguration.class]
2015-02-01 14:56:17.730 DEBUG 1427 --- [ost-startStop-1] o.s.b.c.e.ServletContextInitializerBeans : Created Filter initializer for bean 'characterEncodingFilter'; order=-2147483648, resource=class path resource [org/springframework/boot/autoconfigure/web/HttpEncodingAutoConfiguration.class]
2015-02-01 14:56:17.730 DEBUG 1427 --- [ost-startStop-1] o.s.b.c.e.ServletContextInitializerBeans : Created Filter initializer for bean 'hiddenHttpMethodFilter'; order=2147483647, resource=class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.class]
2015-02-01 14:56:17.743 DEBUG 1427 --- [ost-startStop-1] o.s.b.c.e.ServletContextInitializerBeans : Created EventListener initializer for bean 'requestContextListener'; order=2147483647, resource=class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]

Reference:
https://github.com/spring-projects/spring-boot/issues/2177

Friday, January 30, 2015

org.apache.jasper.JasperException: The absolute uri: http://www.springframework.org/security/tags cannot be resolved in either web.xml or the jar files deployed with this application

You can encounter the following exception:

org.apache.jasper.JasperException: The absolute uri: http://www.springframework.org/security/tags cannot be resolved in either web.xml or the jar files deployed with this application

Add the following line in your 'build.gradle' file:

compile("org.springframework.security:spring-security-taglibs");

<security:debug /> in Spring Boot

To have the same effect with '<security:debug />' in Spring Boot,

add the following line to your 'application.properties':

logging.level.org.springframework.security=DEBUG

Reference:
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html

SLF4J: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError.

You can encounter the following warning:

SLF4J: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError.
SLF4J: See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.

Remove one of them followed by your intention.

SLF4J: Class path contains multiple SLF4J bindings.

You can encounter the following warning:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/izeye/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-log4j12/1.7.7/58f588119ffd1702c77ccab6acb54bfb41bed8bd/slf4j-log4j12-1.7.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/izeye/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.1.2/b316e9737eea25e9ddd6d88eaeee76878045c6b2/logback-classic-1.1.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]

Remove either the Log4J or the Logback followed by your intention.

Unable to find a single main class from the following candidates [com.izeye.app1.Application, com.izeye.app2.Application]

You can encounter the following error when you try to execute a 'bootRun' task:

* What went wrong:
Execution failed for task ':findMainClass'.
> Unable to find a single main class from the following candidates [com.izeye.app1.Application, com.izeye.app2.Application]

Add the following line in your 'build.gradle':

mainClassName = "com.izeye.app1.Application"

Thursday, January 29, 2015

Check 'undefined' in JavaScript

To check 'undefined' in JavaScript,

you can do the following:

console.log(typeof a === "undefined")
true

You can print the type of an 'undefined' variable as follows:

console.log(typeof a);
undefined

and you can print the type of the 'undefined' itself as follows:

console.log(typeof (typeof a));
string

Reference:
http://stackoverflow.com/questions/3390396/how-to-check-for-undefined-in-javascript

Wednesday, January 28, 2015

Prevent exporting a method in a repository in Spring Data REST

To prevent exporting a method in a repository in Spring Data REST,

you can do the following:

@RestResource(exported = false)
Customer save(Customer customer);

Reference:
https://github.com/spring-projects/spring-data-rest/wiki/Configuring-the-REST-URL-path#hiding-repository-crud-methods

Consume Spring Data REST HATEOAS HAL with RestTemplate

When you get Spring Data REST HATEOAS HAL in a web browser,

you will get the following result:

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:18080/api/customers?page=0&size=100{&sort}",
      "templated" : true
    },
    "search" : {
      "href" : "http://localhost:18080/api/customers/search"
    }
  },
  "_embedded" : {
    "customers" : [ {
      "firstName" : "Jack",
      "lastName" : "Bauer",
      "_links" : {
        "self" : {
          "href" : "http://localhost:18080/api/customers/1"
        }
      }
    }, {
      "firstName" : "Chloe",
      "lastName" : "O'Brian",
      "_links" : {
        "self" : {
          "href" : "http://localhost:18080/api/customers/2"
        }
      }
    }, {
      "firstName" : "Kim",
      "lastName" : "Bauer",
      "_links" : {
        "self" : {
          "href" : "http://localhost:18080/api/customers/3"
        }
      }
    }, {
      "firstName" : "David",
      "lastName" : "Palmer",
      "_links" : {
        "self" : {
          "href" : "http://localhost:18080/api/customers/4"
        }
      }
    }, {
      "firstName" : "Michelle",
      "lastName" : "Dessler",
      "_links" : {
        "self" : {
          "href" : "http://localhost:18080/api/customers/5"
        }
      }
    } ]
  },
  "page" : {
    "size" : 100,
    "totalElements" : 5,
    "totalPages" : 1,
    "number" : 0
  }
}

but when you get it with RestTemplate,

you will get the following result:

{
  "links" : [ {
    "rel" : "self",
    "href" : "http://localhost:18080/api/customers?page=0&size=100{&sort}"
  }, {
    "rel" : "search",
    "href" : "http://localhost:18080/api/customers/search"
  }, {
    "rel" : "customer",
    "href" : "http://localhost:18080/api/customers/1"
  }, {
    "rel" : "customer",
    "href" : "http://localhost:18080/api/customers/2"
  }, {
    "rel" : "customer",
    "href" : "http://localhost:18080/api/customers/3"
  }, {
    "rel" : "customer",
    "href" : "http://localhost:18080/api/customers/4"
  }, {
    "rel" : "customer",
    "href" : "http://localhost:18080/api/customers/5"
  } ],
  "content" : [ ],
  "page" : {
    "size" : 100,
    "totalElements" : 5,
    "totalPages" : 1,
    "number" : 0
  }
}

Surprisingly the "content" is empty.

This is due to Accept header.

A web browser uses the following Accept header:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

but RestTemplate uses the following Accept header:

Accept: text/plain, application/json, application/*+json, */*

So the content type in a web browser will be as follows:

Content-Type:application/hal+json;charset=UTF-8

but the content type in RestTemplate will be as follows:

Content-Type: application/x-spring-data-compact+json;charset=UTF-8

You can consume it correctly with RestTemplate as follows:

@Test
public void test() {
RestTemplate restTemplate = restTemplate();

String url = "http://localhost:{port}/api/customers?page={page}&size={size}";

ResponseEntity<PagedResources<Customer>> responseEntity = restTemplate.exchange(
url, HttpMethod.GET, null,
new ParameterizedTypeReference<PagedResources<Customer>>() {},
port, 0, 100);
PagedResources<Customer> resources = responseEntity.getBody();
List<Customer> customers = new ArrayList(resources.getContent());
System.out.println(customers);
System.out.println(customers.get(0).getClass());
}

private RestTemplate restTemplate() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.registerModule(new Jackson2HalModule());

MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json"));
converter.setObjectMapper(mapper);
return new RestTemplate(Arrays.asList(converter));
}

Reference:
http://stackoverflow.com/questions/23239052/why-does-resttemplate-not-bind-response-representation-to-pagedresources

Use generics with RestTemplate

To use generics with RestTemplate,

you can use ParameterizedTypeReference as follows:

ResponseEntity<PagedResources<Customer>> responseEntity = restTemplate.exchange(
url, HttpMethod.GET, null,
new ParameterizedTypeReference<PagedResources<Customer>>() {},
port, 0, 100);
PagedResources<Customer> resources = responseEntity.getBody();
List<Customer> customers = new ArrayList(resources.getContent());
System.out.println(customers);
System.out.println(customers.get(0).getClass());

exchange() method is only supported.

Reference:
http://www.java-allandsundry.com/2014/01/consuming-spring-hateoas-rest-service.html

Send a HTTP request having a custom Accept header with RestTemplate

To send a HTTP request having a custom Accept header with RestTemplate,

you can do it as follows:

RestTemplate restTemplate = new RestTemplate();

HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<Void> requestEntity = new HttpEntity<Void>(headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
url, HttpMethod.GET, requestEntity, String.class, port, 0, 100);
System.out.println(responseEntity.getBody());

Reference:
http://stackoverflow.com/questions/19238715/how-to-set-an-accept-header-on-spring-resttemplate-request

Tuesday, January 27, 2015

Configure HTTP and HTTPS in Spring Boot

To configure HTTP and HTTPS in Spring Boot,

add the following properties in application.properties:

http.port=80

server.port=443
server.ssl.key-store=/home/izeye/keystore
server.ssl.key-store-password=keystore
server.ssl.key-password=privatekey

and add an embedded servlet container customer as follows:

@Configuration
public class TomcatConfig {

    @Value("${http.port}")
    private int httpPort;

    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
        return new EmbeddedServletContainerCustomizer() {
            @Override
            public void customize(ConfigurableEmbeddedServletContainer container) {
                if (container instanceof TomcatEmbeddedServletContainerFactory) {
                    TomcatEmbeddedServletContainerFactory containerFactory =
                            (TomcatEmbeddedServletContainerFactory) container;

                    Connector connector = new Connector(TomcatEmbeddedServletContainerFactory.DEFAULT_PROTOCOL);
                    connector.setPort(httpPort);
                    containerFactory.addAdditionalTomcatConnectors(connector);
                }
            }
        };
    }

}

Reference:
http://izeye.blogspot.kr/2015/01/configure-https-with-self-signed.html

Configure HTTPS with a self-signed certificate in Spring Boot

To configure HTTPS with a self-signed certificate in Spring Boot,

create a new keystore having a self-signed certificate as follows:

keytool -genkey -alias tomcat -keyalg RSA -keystore keystore

Copy the file to 'src/main/resources/'

and add the following properties in application.properties:

server.ssl.key-store=classpath:keystore
server.ssl.key-store-password=keystore
server.ssl.key-password=privatekey

If you run it as a jar file,

a location for keystore should be on a filesystem as follows:

server.ssl.key-store=/Users/izeye/keystore

References:
http://tomcat.apache.org/tomcat-8.0-doc/ssl-howto.html
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-configure-ssl

Monday, January 26, 2015

Add multiple filters having same type in Spring Boot

To add multiple filters having same type in Spring Boot,

you can do the following:

@Bean
public FilterRegistrationBean remoteAddressFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setName("test1");
RemoteAddrFilter filter = new RemoteAddrFilter();
filter.setAllow("127.0.0.1");
// filter.setAllow("0:0:0:0:0:0:0:1");
filterRegistrationBean.setFilter(filter);
filterRegistrationBean.addUrlPatterns("/gs/serving-web-content/testParameters");
return filterRegistrationBean;
}

@Bean
public FilterRegistrationBean remoteAddressFilter2() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
RemoteAddrFilter filter = new RemoteAddrFilter();
filterRegistrationBean.setName("test2");
filter.setAllow("127.0.0.1");
// filter.setAllow("0:0:0:0:0:0:0:1");
filterRegistrationBean.setFilter(filter);
filterRegistrationBean.addUrlPatterns("/gs/serving-web-content/testHeaders");
return filterRegistrationBean;
}

You should set a name for each filter.

How to add a RemoteAddrValve or RemoteAddrFilter in Spring Boot

To add a RemoteAddrValve in Spring Boot,

you can do the following:

@Component
public class TomcatRemoteAddrValveCustomizer implements EmbeddedServletContainerCustomizer {

@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
TomcatEmbeddedServletContainerFactory tomcatContainer =
(TomcatEmbeddedServletContainerFactory) container;
RemoteAddrValve remoteAddrValve = new RemoteAddrValve();
// remoteAddrValve.setAllow("127.0.0.1");
remoteAddrValve.setAllow("0:0:0:0:0:0:0:1");
tomcatContainer.addContextValves(remoteAddrValve);
}

}

To add a RemoteAddrFilter in Spring Boot,

you can do the following:

@Bean
public FilterRegistrationBean remoteAddressFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
RemoteAddrFilter filter = new RemoteAddrFilter();
// filter.setAllow("127.0.0.1");
filter.setAllow("0:0:0:0:0:0:0:1");
filterRegistrationBean.setFilter(filter);
filterRegistrationBean.addUrlPatterns("/gs/serving-web-content/testParameters");
return filterRegistrationBean;
}

References:
http://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#Remote_Address_Filter
http://stackoverflow.com/questions/10498237/how-can-i-restrict-access-to-certain-urls-by-source-ip-in-tomcat
http://tomcat.apache.org/tomcat-8.0-doc/config/filter.html#Remote_Address_Filter
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-customizing-embedded-containers
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-embedded-container-servlets-and-filters

How to add a filter in Spring Boot

To add a filter in Spring Boot,

you can do the following:

@Bean
public FilterRegistrationBean remoteAddressFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
RemoteAddrFilter filter = new RemoteAddrFilter();
// filter.setAllow("127.0.0.1");
filter.setAllow("0:0:0:0:0:0:0:1");
filterRegistrationBean.setFilter(filter);
filterRegistrationBean.addUrlPatterns("/gs/serving-web-content/testParameters");
return filterRegistrationBean;
}

Reference:
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-embedded-container-servlets-and-filters

Sunday, January 25, 2015

Saturday, January 24, 2015

Install a package by Bower

For example, to install UI Bootstrap,

you can use the following command:

bower install angular-bootstrap

You can find the package

in 'bower_components' under your current directory you executed the command.

Reference:
http://bower.io/

npm ERR! Error: ENOENT, lstat '/usr/local/lib/node_modules/bower/node_modules/mout/function/series.js'

When you try to install Bower by npm as follows:

sudo npm install -g bower

you can encounter the following error:

npm ERR! Error: ENOENT, lstat '/usr/local/lib/node_modules/bower/node_modules/mout/function/series.js'

In my case, it's resolved with upgrading Node.js and npm as follows:

http://izeye.blogspot.kr/2015/01/upgrade-nodejs-and-npm.html

Upgrade Node.js and npm

Check your current Node.js and npm versions as follows:

$ node -v
v0.8.14
$ npm -v
1.1.65
$

Upgrade Node.js and npm by npm as follows:

$ sudo npm cache clean -f
$ sudo npm install -g n
$ sudo n stable
$

Check your upgraded Node.js and npm versions as follows:

$ node -v
v0.10.35
$ npm -v
1.4.28
$

Reference:
http://davidwalsh.name/upgrade-nodejs

Thursday, January 22, 2015

HTTP headers and parameters' case sensitivity in Spring framework

In Spring framework,

HTTP headers' field names are case-insensitive

but HTTP parameters' names are case-sensitive.

Reference:
http://stackoverflow.com/questions/5258977/are-http-headers-case-sensitive

HTTP header size limit

There's no HTTP header size limit

but Tomcat has HTTP header size limit.

In Tomcat 7, it's 8KB

and you can set 'maxHttpHeaderSize' to change it:

The maximum size of the request and response HTTP header, specified in bytes. If not specified, this attribute is set to 8192 (8 KB).

You can find a sample for testing Tomcat HTTP header size limit as follows:

https://github.com/izeye/samples-spring-boot/blob/master/src/test/java/samples/springboot/gs/serving_web_content/TestControllerTests.java

References:
http://stackoverflow.com/questions/686217/maximum-on-http-header-values
http://tomcat.apache.org/tomcat-7.0-doc/config/http.html

Sunday, January 18, 2015

[error] [client 127.0.0.1] client denied by server configuration: /home/izeye/programs/apache2.2/htdocs/server-status

You can encounter the following error in Apache:

[error] [client 127.0.0.1] client denied by server configuration: /home/izeye/programs/apache2.2/htdocs/server-status

Add 'Allow from 127.' to the 'conf/extra/httpd-info.conf' file as follows:

<Location /server-status>
    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from 10.
    Allow from 127.
</Location>

References:
https://wiki.apache.org/httpd/ClientDeniedByServerConfiguration
http://httpd.apache.org/docs/2.2/howto/access.html

How to use two data sources with JPA in Spring Boot

In Spring Boot,

if you define another data source,

the default data source won't be created.

So you have to define your original data source as a bean as follows:

@Configuration
public class DataSourceConfig {

@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}

}

If you use JPA,

you should use @Primary annotation for auto-configuration.

Reference:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-two-datasources

Wednesday, January 14, 2015

Conditional appender in Logback

To use a conditional appender in Logback,

use an 'if' element in logback.xml as follows:

    <root level="INFO">
        <if condition='!property("spring.profiles.active").contains("production")'>
            <then>
                <appender-ref ref="CONSOLE" />
            </then>
        </if>
        <appender-ref ref="DEBUG_LOG_APPENDER" />
    </root>

To use conditional processing,

you should add Janino dependency to build.gradle as follows:

compile("org.codehaus.janino:janino:2.7.7")

References:
http://logback.qos.ch/manual/configuration.html
http://logback.qos.ch/setup.html#janino

Monday, January 12, 2015

How to use WebJars in Spring Boot

In Spring Boot, to use WebJars,

add a dependency to a build.gradle file as follows:

compile("org.webjars:jquery:2.1.3")

and use it as follows:

<script th:src="@{/webjars/jquery/2.1.3/jquery.min.js}"></script>

Reference:
http://spring.io/blog/2014/01/03/utilizing-webjars-in-spring-boot

Saturday, January 10, 2015

org.springframework.security.authentication.InternalAuthenticationServiceException: UserDetailsService returned null, which is an interface contract violation

You can encounter the following exception:

org.springframework.security.authentication.InternalAuthenticationServiceException: UserDetailsService returned null, which is an interface contract violation

UserDetailsService.loadUserByUsername() shouldn't return a null value as described in Javadoc.

When the value is null, it should throw a UsernameNotFoundException as follows:

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userRepository.findByUsername(username);
    if (user == null) {
      throw new UsernameNotFoundException(username);
    }
    return user;
  }

How to use AsciiDoctor Gradle plugin

To use AsciiDoctor Gradle plugin,

add the following configuration to build.gradle:

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.0'
    }
}

apply plugin: 'org.asciidoctor.gradle.asciidoctor'

and put your AsciiDoctor files into the src/asciidoc directory.

Run the 'asciidoctor' task.

Then you can find your output files in the build/asciidoc directory.

It seems that the plugin doesn't support an 'include' directive with a remote file yet.

To use an 'include' directive with a remote file,

you should add the following configuration to build.gradle.

asciidoctor {
    options = [
        attributes: [
            'allow-uri-read': ''
        ]
    ]
}

References:
http://asciidoctor.org/docs/asciidoctor-gradle-plugin/
https://github.com/asciidoctor/asciidoctor-gradle-plugin
https://github.com/asciidoctor/asciidoctor-gradle-plugin/issues/146
http://asciidoctor.org/docs/user-manual/#include-content-from-a-uri
http://asciidoctor.org/docs/user-manual/#running-asciidoctor-securely

asciidoctor: ERROR: test.adoc: line 1: only book doctypes can contain level 0 sections

You can encounter the following error:

asciidoctor: ERROR: test.adoc: line 1: only book doctypes can contain level 0 sections

As the error message shows,

you can't contain multiple level 0 sections if the doctype is not book.

Reference:
http://asciidoctor.org/docs/user-manual/#sections

How to use AsciiDoctor

To use AsciiDoctor,

install it as follows:

sudo gem install asciidoctor

and just use it as follows:

asciidoctor -S safe -a allow-uri-read,skip-front-matter README.adoc

Reference:
https://github.com/spring-guides/getting-started-guides/wiki/Working-with-AsciiDoctor

Friday, January 9, 2015

[error] Unable to initialize TLS servername extension callback (incompatible OpenSSL version?)

You can encounter the following error:

[error] Unable to initialize TLS servername extension callback (incompatible OpenSSL version?)

It could be related to OpenSSL version as the error message says

but in my case it was related to the location of the LoadModule directive for SSL.

It was solved by moving the following LoadModule directive

to the top on other LoadModule directives.

LoadModule ssl_module /usr/lib64/httpd/modules/mod_ssl.so

Thursday, January 8, 2015

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

If you use a self-signed certificate for a test,

you can encounter the following exception:

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Download the certificate as follows:

http://izeye.blogspot.kr/2015/01/how-to-download-certificate-from-https.html

Copy the keystore not to compromise its integrity:

cp /Library/Java/JavaVirtualMachines/jdk1.8.0_05.jdk/Contents/Home/jre/lib/security/cacerts .

Import the downloaded certificate to the keystore:

keytool -import -alias test -keystore cacerts -file test.pem

Run a Java program with the following VM arguments:

-Djavax.net.ssl.trustStore=/Users/izeye/workspaces/openssl/java/cacerts -Djavax.net.ssl.trustStorePassword=changeit

You can also avoid the exception programmatically

by bypassing the certification validation as follows:

TrustManager[] trustManagers = new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}

@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}

@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagers, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

References:
http://stackoverflow.com/questions/6908948/java-sun-security-provider-certpath-suncertpathbuilderexception-unable-to-find
http://magicmonster.com/kb/prg/java/ssl/pkix_path_building_failed.html
http://www.nakov.com/blog/2009/07/16/disable-certificate-validation-in-java-ssl-connections/

Caused by: java.security.cert.CertificateException: No subject alternative names present

You can encounter the following exception:

Caused by: java.security.cert.CertificateException: No subject alternative names present

If you use an IP address for a common name (CN),

use a domain name.

How to download a certificate from a HTTPS website by OpenSSL

To download a certificate from a HTTPS website by OpenSSL,

use the following command:

openssl s_client -connect www.izeye.com:443

and copy from the following line:

-----BEGIN CERTIFICATE-----

to the following line:

-----END CERTIFICATE-----

and save it as a file like test.pem.

By 'man s_client', you can find the meanings of the options:

s_client - SSL/TLS client program

       -connect host:port
           This specifies the host and optional port to connect to. If not
           specified then an attempt is made to connect to the local host on
           port 4433.

Reference:
http://superuser.com/questions/97201/how-to-save-a-remote-server-ssl-certificate-locally-as-a-file

[error] Init: Unable to read pass phrase [Hint: key introduced or changed before restart?]

You can encounter the following error when you restart Apache:

[error] Init: Unable to read pass phrase [Hint: key introduced or changed before restart?]

You can automate entering the pass phrase for the private key

with the following configuration:

conf/extra/httpd-ssl.conf

#SSLPassPhraseDialog  builtin
SSLPassPhraseDialog  exec:/home/izeye/workspaces/izeye/openssl/pass.sh

pass.sh

#!/bin/bash
echo "1234"

chmod +x pass.sh

Without an execute permission, you will encounter the following error:

[error] Init: Pass phrase incorrect

Reference:
https://wiki.apache.org/httpd/RemoveSSLCertPassPhrase

Wednesday, January 7, 2015

How to show a certificate

To show a certificate,

you can use the following command:

openssl x509 -in cacert.pem -noout -text

The meanings of the options are as follows:

       -in filename
           This specifies the input filename to read a certificate
           from or standard input if this option is not specified.

       -noout
           this option prevents output of the encoded version of the
           request.

       -text
           prints out the certificate in text form. Full details are
           output including the public key, signature algorithms,
           issuer and subject names, serial number any extensions
           present and any trust settings.

Tuesday, January 6, 2015

How to work with HTTPS in Fiddler

To work with HTTPS in Fiddler,

Do as follows:

Tools -> Fiddler Options -> HTTPS

Check 'Decrypt HTTPS traffic'

Fiddler works as a HTTPS proxy to inspect the content of HTTPS traffic.

How to set up HTTPS for Apache in CentOS

To set up HTTPS for Apache in CentOS,

you can do as follows:

1. Create a private key:

http://izeye.blogspot.kr/2015/01/how-to-create-private-key.html

2. Create a test certificate:

http://izeye.blogspot.kr/2014/12/create-self-signed-test-certificate-in.html

3. Install mod_ssl:

sudo yum install mod_ssl

4. Configure Apache:

In conf/httpd.conf file:

LoadModule ssl_module /usr/lib64/httpd/modules/mod_ssl.so

Include conf/extra/httpd-ssl.conf

In conf/extra/httpd-ssl.conf file:

SSLPassPhraseDialog  exec:/home/izeye/workspaces/izeye/openssl/pass.sh

ServerName www.izeye.com:443

SSLCertificateFile "/home/izeye/workspaces/izeye/openssl/cacert.pem"

SSLCertificateKeyFile "/home/izeye/workspaces/izeye/openssl/privkey.pem"

In pass.sh:

#!/bin/bash
echo "1234"

Add an execute permission:

chmod +x pass.sh

5. Restart Apache:

sudo bin/apachectl restart

Reference:
http://wiki.centos.org/HowTos/Https

Sunday, January 4, 2015

How to create a private key

To create a RSA private key,

you can use the following command:

openssl genrsa -des3 -out privkey.pem 2048

To create a DSA private key,

you can use the following commands:

openssl dsaparam -out dsaparam.pem 2048

openssl gendsa -des3 -out privkey.pem dsaparam.pem

Reference:
https://www.openssl.org/docs/HOWTO/keys.txt

@EnableWebSecurity vs. @EnableWebMvcSecurity

What is the difference between @EnableWebSecurity and @EnableWebMvcSecurity?

@EnableWebMvcSecurity provides @EnableWebSecurity's functions

and integration with Spring MVC

like automatic CSRF (Cross Site Request Forgery) token inclusion.

Since Spring Security 4.0.0.RC1, @EnableWebMvcSecurity is deprecated.

You can use @EnableWebSecurity instead for the same purpose since the version.

References:
http://stackoverflow.com/questions/21195615/upgrading-spring-security-to-3-2-0-release-no-longer-provides-csrf-token-in-spri
http://docs.spring.io/spring-security/site/docs/3.2.x/guides/hellomvc.html#logging-out
https://jira.spring.io/browse/SEC-2436
https://jira.spring.io/browse/SEC-2463
https://jira.spring.io/browse/SEC-2790

Validate Travis CI configuration file, '.travis.yml' in web

To validate Travis CI configuration, '.travis.yml' in web,

you can use the following website:

http://lint.travis-ci.org/

Asciidoctor Chrome Extension

You can render an AsciiDoc file in Chrome by the Asciidoctor Chrome Extension.

You can install the Asciidoctor Chrome Extension as follows:

1. Install the extension from Chrome Web Store.

2. Check 'Allow access to file URLs' in 'chrome://extensions/'.

3. Open a local or remote AsciiDoc file in Chrome.

Reference:
https://github.com/asciidoctor/asciidoctor-chrome-extension

Saturday, January 3, 2015

Group chat, Flowdock

Group chat, Flowdock is free for teams of five and non-profits.

It provides both web-based application and native application.

It also provides both Android application and iOS application.

Reference:
https://www.flowdock.com/

Friday, January 2, 2015

What is ^ in Clojure?

In Clojure, ^ is a map for metadata like type.

You can use it as follows:

(defn purchase-order [id date amount]
  ^{:type ::PurchaseOrder}
  {:id id :date date :amount amount})

(def my-order (purchase-order 10 (java.util.Date.) 100.0))

(println my-order)

(println (type my-order))

Then you can get the following result:

{:id 10, :date #inst "2015-01-02T12:46:44.626-00:00", :amount 100.0}
:user/PurchaseOrder

Reference:
http://clojure.org/reader

What is {} in Clojure?

In Clojure, {} is a persistent array-map.

You can check the type as follows:

(println (type {}))

Then you can get the result as follows:

clojure.lang.PersistentArrayMap

What is array-map?

array-map is a form to convert from an array to a map

using the elements in the array as a key, a value, a key, a value, and so on.

References:
https://clojuredocs.org/clojure.core/array-map
http://clojure.org/data_structures#Data Structures-ArrayMaps

How to get a type in Clojure

To get a type in Clojure,

you can use the type macro as follows:

(println (type 10))

Then you will get the following result:

java.lang.Long

Reference:
https://clojuredocs.org/clojure.core/type

How to change a Git commit message

To change a Git commit message,

you can use the following command:

git commit --amend

Reference:
http://stackoverflow.com/questions/179123/edit-an-incorrect-commit-message-in-git

Thursday, January 1, 2015

How to replace string by regular expression in IntelliJ

To replace string by regular expression in IntelliJ,

do as follows:

Press Ctrl + 'R'.

Check 'Regex'.

Reference:
https://www.jetbrains.com/idea/help/finding-and-replacing-text-in-file.html

GitHub HTML preview

You can preview an HTML file in GitHub as follows:

http://htmlpreview.github.io/?<URL>

This is an example:

http://htmlpreview.github.io/?https://github.com/karlcow/markdown-testsuite/blob/master/markdown-spec.html

ImportError: No module named argparse

You can encounter the following error when executing a python script:

ImportError: No module named argparse

To fix it, you can use the following command:

easy_install argparse

How to inline expression in Thymeleaf

To inline expression in Thymeleaf,

you can do it as follows:

<p th:inline="text" style="font-size: 11px; color: gray">
    [[${link.createdTime}]] [[${link.sharerUsername}]]
</p>

Reference:
http://www.thymeleaf.org/doc/usingthymeleaf.html