Saturday, February 28, 2015

Unable to initialize POM pom-default.xml: Failed to validate POM for project com.izeye:samples-spring-boot-branches at /Users/izeye/IdeaProjects/samples-spring-boot-branches/build/publications/maven/pom-default.xml

When you use Spring Boot with Gradle and run the 'publishMavenPublicationToMavenLocal' task,

you can encounter the following error:

* What went wrong:
Execution failed for task ':publishMavenPublicationToMavenLocal'.
> Failed to publish publication 'maven' to repository 'MavenLocal'
   > Unable to initialize POM pom-default.xml: Failed to validate POM for project com.izeye:samples-spring-boot-branches at /Users/izeye/IdeaProjects/samples-spring-boot-branches/build/publications/maven/pom-default.xml

It's caused by absence of versions of artifacts provided by 'spring-boot' plugin.

You can use the dependency management plugin as follows:

buildscript {
    repositories {
        jcenter()
        maven { url "http://repo.spring.io/snapshot" }
        maven { url "http://repo.spring.io/libs-milestone" }
        maven { url "http://repo.spring.io/libs-release" }
        mavenLocal()
    }

    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.2.RELEASE")

        classpath("io.spring.gradle:dependency-management-plugin:0.4.0.RELEASE")
    }
}

apply plugin: 'io.spring.dependency-management'

dependencyManagement {
    imports {
        mavenBom 'org.springframework.boot:spring-boot-dependencies:1.2.2.RELEASE'
    }
}

Reference:
https://github.com/spring-gradle-plugins/dependency-management-plugin

Wednesday, February 25, 2015

Revert the last commit and its change in Git

To revert the last commit and its change in Git,

do the following:

git reset --hard HEAD~1

Reference:
http://stackoverflow.com/questions/927358/how-to-undo-the-last-commit

Tuesday, February 24, 2015

Failed to transfer file: http://1.2.3.4:8080/repository/internal/com/izeye/test/1.0.1/test-1.0.1.jar. Return code is: 401

When you try to upload an artifact to Apache Archiva,

you can encounter the following error suddenly:

Failed to transfer file: http://1.2.3.4:8080/repository/internal/com/izeye/test/1.0.1/test-1.0.1.jar. Return code is: 401

Visit the following page:

http://1.2.3.4:8080/#welcome

When you try to login, you will encounter the following message:

Password Expired, You must change your password.

I didn't set up SMTP.

So I couldn't find an easy way to fix.

I just re-installed it.

Saturday, February 21, 2015

How to change Spring Data REST JSON Date format in Spring Boot

The default Spring Data REST JSON Date format in Spring Boot is as follows:

2015-02-21T07:03:18.000+0000

To change the default Spring Data REST JSON Date format in Spring Boot,

add the following property in your application.properties:

spring.jackson.date-format=yyyy-MM-dd HH:mm:ss

Now you will get the following result:

2015-02-21 16:03:18

Reference:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/html/common-application-properties.html

Thursday, February 12, 2015

Spring Boot event flow

The following logs show a event flow in a Spring Boot web application:

SpringApplicationEvent: ApplicationStartedEvent
SpringApplicationEvent: ApplicationEnvironmentPreparedEvent
SpringApplicationEvent: ApplicationPreparedEvent
Application$$EnhancerBySpringCGLIB$$b8c60715: @PostConstruct
SomeRepository: @PostConstruct
SomeService: @PostConstruct
SomeController: @PostConstruct
ApplicationEvent: ContextRefreshedEvent
ApplicationEvent: EmbeddedServletContainerInitializedEvent
ApplicationEvent: ServletRequestHandledEvent
...
ApplicationEvent: ServletRequestHandledEvent
ApplicationEvent: ContextClosedEvent
SomeController: @PreDestroy
SomeService: @PreDestroy
SomeRepository: @PreDestroy
Application$$EnhancerBySpringCGLIB$$b8c60715: @PreDestroy

ApplicationEvent is a Spring event

and SpringApplicationEvent is a Spring Boot event.

You can define your event handlers by implementing ApplicationListener.

But note that Spring Boot events can't be caught by ApplicationListener beans

because all of them are fired before creating the beans.

Use SpringApplication.addListeners() for Spring Boot events instead.

You can find this sample project in the following link:

https://github.com/izeye/samples-spring-boot-branches/tree/event

---

Source-added versions:

Web:

SpringApplicationEvent: ApplicationStartedEvent from org.springframework.boot.SpringApplication@5bcab519
SpringApplicationEvent: ApplicationEnvironmentPreparedEvent from org.springframework.boot.SpringApplication@5bcab519
SpringApplicationEvent: ApplicationPreparedEvent from org.springframework.boot.SpringApplication@5bcab519
Application$$EnhancerBySpringCGLIB$$29fbb36b: @PostConstruct
SomeRepository: @PostConstruct
SomeService: @PostConstruct
SomeController: @PostConstruct
ApplicationEvent: ContextRefreshedEvent from org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1990a65e: startup date [Mon Mar 02 21:04:17 KST 2015]; root of context hierarchy
ApplicationEvent: EmbeddedServletContainerInitializedEvent from org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer@7882c44a
ApplicationEvent: ServletRequestHandledEvent from org.springframework.web.servlet.DispatcherServlet@2990747b
...
ApplicationEvent: ContextClosedEvent from org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1990a65e: startup date [Mon Mar 02 20:42:31 KST 2015]; root of context hierarchy
SomeController: @PreDestroy
SomeService: @PreDestroy
SomeRepository: @PreDestroy
Application$$EnhancerBySpringCGLIB$$29fbb36b: @PreDestroy

Non-web:

SpringApplicationEvent: ApplicationStartedEvent from org.springframework.boot.SpringApplication@5b275dab
SpringApplicationEvent: ApplicationEnvironmentPreparedEvent from org.springframework.boot.SpringApplication@5b275dab
SpringApplicationEvent: ApplicationPreparedEvent from org.springframework.boot.SpringApplication@5b275dab
Application$$EnhancerBySpringCGLIB$$de573e5a: @PostConstruct
SomeRepository: @PostConstruct
SomeService: @PostConstruct
ApplicationEvent: ContextRefreshedEvent from org.springframework.context.annotation.AnnotationConfigApplicationContext@4923ab24: startup date [Mon Mar 02 20:52:40 KST 2015]; root of context hierarchy
...
ApplicationEvent: ContextClosedEvent from org.springframework.context.annotation.AnnotationConfigApplicationContext@4923ab24: startup date [Mon Mar 02 20:52:40 KST 2015]; root of context hierarchy
SomeService: @PreDestroy
SomeRepository: @PreDestroy
Application$$EnhancerBySpringCGLIB$$de573e5a: @PreDestroy

Reference:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-application-events-and-listeners

How to render a part of Javadoc of a source file in IntelliJ on Mac

To render a part of Javadoc of source file in IntelliJ on Mac,

go to any line having Javadoc that you want to render

and use the following shortcut:

control + J

Reference:
http://stackoverflow.com/questions/11053144/how-to-see-javadoc-in-intellij-idea

Tuesday, February 10, 2015

Support class autowiring for transaction-enabled beans in Spring Boot

Support class autowiring for transaction-enabled beans in Spring Boot,

you should add the following annotation:

@EnableTransactionManagement(proxyTargetClass = true)

Reference:
http://stackoverflow.com/questions/28311091/aspectj-not-working-after-transaction-configuration-in-spring-boot

Sunday, February 8, 2015

Get lastest HTTP requests and responses' information in Spring Boot

To get lastest HTTP requests and responses' information in Spring Boot,

add Spring Boot Actuator and check the '/trace' endpoint.

You will get the following information:

[{"timestamp":1423401573491,"info":{"method":"GET","path":"/trace","headers":{"request":{"host":"localhost:8080","connection":"keep-alive","cache-control":"max-age=0","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36","accept-encoding":"gzip, deflate, sdch","accept-language":"ko,zh-CN;q=0.8,zh;q=0.6,en-US;q=0.4,en;q=0.2","cookie":"JSESSIONID=0C5D304BACC47BAFB28A4F1044501560; _ga=GA1.1.2128301213.1414071979"},"response":{"X-Application-Context":"application","Content-Type":"application/json;charset=UTF-8","Transfer-Encoding":"chunked","Date":"Sun, 08 Feb 2015 13:19:32 GMT","status":"200"}}}}]

It doesn't provide parameters' information yet.

I think it would be good if provided.

A discussion on it is in progress now at:

https://github.com/spring-projects/spring-boot/issues/2458

Reference:
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#production-ready-tracing

org.xml.sax.SAXParseException: Attribute name "attribute-without-value" associated with an element type "div" must be followed by the ' = ' character.

When you use Thymeleaf in Spring Boot,

you can encounter the following exception:

org.xml.sax.SAXParseException: Attribute name "attribute-without-value" associated with an element type "div" must be followed by the ' = ' character.

In Spring Boot, Thymeleaf mode's default value is HTML5.

So you should change the mode to LEGACYHTML5

by adding the following property in your 'application.properties':

spring.thymeleaf.mode=LEGACYHTML5

And you should add the following dependency in your 'build.gradle':

compile("net.sourceforge.nekohtml:nekohtml:1.9.21")

If not, you will encounter the following exception:

org.thymeleaf.exceptions.ConfigurationException: Cannot perform conversion to XML from legacy HTML: The nekoHTML library is not in classpath. nekoHTML 1.9.15 or newer is required for processing templates in "LEGACYHTML5" mode [http://nekohtml.sourceforge.net]. Maven spec: "net.sourceforge.nekohtml::nekohtml::1.9.15". IMPORTANT: DO NOT use versions of nekoHTML older than 1.9.15.

You can find a sample for this as follows:

https://github.com/izeye/samples-spring-boot-branches/tree/thymeleaf

Reference:
http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

Saturday, February 7, 2015

How to ignore Spring Security login for a test or local environment in Spring Boot

To ignore Spring Security login for a test or local environment in Spring Boot,

you can add the following property

to your application-test.properties or application-local.properties:

security.ignored=/**

Reference:
http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

Friday, February 6, 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

You should change from:

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userRepository.findByUsername(username);
    }

to:

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

Thursday, February 5, 2015

Error running spring-boot-admin-sample [clean]: No valid Maven installation found. Either set the home directory in the configuration dialog or set the M2_HOME environment variable on your system.


You can encounter the following error in IntelliJ on Mac:

Error running spring-boot-admin-sample [clean]: No valid Maven installation found. Either set the home directory in the configuration dialog or set the M2_HOME environment variable on your system.

Setting M2_HOME doesn't work.

You'd better set your Maven home directory in IntelliJ as follows:

Preferences -> Maven -> Maven home directory

Reference:
http://stackoverflow.com/questions/7053666/maven-home-m2-home-not-being-picked-up-by-intellij-idea

Wednesday, February 4, 2015

Print all HTTP response headers in jQuery

To print all HTTP response header in jQuery,

you can use the following code:

$(document).ready(function () {
    $.ajax({
        url: "http://localhost:8080/greeting"
    }).then(function (data, status, request) {
        console.log(request.getAllResponseHeaders());
    });
});

Note that it does NOT support CORS headers.

Reference:
http://bugs.jquery.com/ticket/10338

java.lang.NoSuchMethodError: org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runLeaf(Lorg/junit/runners/model/Statement;Lorg/junit/runner/Description;Lorg/junit/runner/notification/RunNotifier;)V

You can encounter the following error:

java.lang.NoSuchMethodError: org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runLeaf(Lorg/junit/runners/model/Statement;Lorg/junit/runner/Description;Lorg/junit/runner/notification/RunNotifier;)V

In my case, I've got 2 JUnit dependencies with two different versions:

junit-4.7
junit-4.12

log4jdbc-remix has a JUnit dependency as compile scope,

so I excluded it as follows:

    compile("org.lazyluke:log4jdbc-remix:0.2.7") {
        exclude module: 'junit'
    }

Tuesday, February 3, 2015

Enable 'org.thymeleaf' TRACE log in Spring Boot

To enable 'org.thymeleaf' TRACE log in Spring Boot,

trying to add the following property in your application.properties won't work:

logging.level.org.thymeleaf=TRACE

because of LevelRemappingAppender.

Reference org.springframework.boot.logging.logback.DefaultLogbackConfiguration or defaults.xml.

So you should add the following properties:

logging.level.org.thymeleaf=TRACE
logging.level.org.springframework.boot=TRACE

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

Monday, February 2, 2015

Use JSP and Thymeleaf in Spring Boot

You can find a sample using JSP and Thymeleaf in Spring Boot in the following link:

https://github.com/izeye/samples-spring-boot-branches/tree/jsp-and-thymeleaf

application.properties has the following properties:

spring.view.prefix: /WEB-INF/jsp/
spring.view.suffix: .jsp

spring.thymeleaf.cache=false
spring.thymeleaf.excluded-view-names=welcome

If you want to use some JSP views,

you should specify the view names to the 'spring.thymeleaf.excluded-view-names' property.

If not,

there's no chance to render them.

You'll get a 500 error indicating that there's no Thymeleaf template for the view name.

I can't understand why ThymeleafViewResolver returns a view

even when it doesn't have any template for the view name.

It prevents JSP from rendering it.

If it could return null instead of an invalid view,

the 'spring.thymeleaf.excluded-view-names' property would not be necessary.

Any idea?

Reference:
http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

Print all functions defined in window in JavaScript

To print all function defined in window in JavaScript,

use the following code:

    for (var propertyName in this) {
        var property = this[propertyName];
        if (typeof(property) === 'function') {
            console.log(property);
        }
    }

Reference:
http://stackoverflow.com/questions/152483/is-there-a-way-to-print-all-methods-of-an-object-in-javascript

Sunday, February 1, 2015

Set custom locations for scanning repositories and entities of Spring Data JPA in Spring Boot

To set custom locations

for scanning repositories and entities of Spring Data JPA in Spring Boot,

add the following annotations:

@EnableJpaRepositories(basePackages = "com.izeye.application.core.repository")
@EntityScan(basePackages = "com.izeye.application.core.domain")

Use SiteMesh 3 with Spring Security in Spring Boot

The following link is a sample project using SiteMesh 3 with Spring Security in Spring Boot:

https://github.com/izeye/samples-spring-boot-branches/tree/sitemesh-and-spring-security

You should place the filter for SiteMesh after the filter for Spring Security.

If not,

you will get the following error in your web browser:

This webpage has a redirect loop

The webpage at http://localhost:8080/login has resulted in too many redirects. Clearing your cookies for this site or allowing third-party cookies may fix the problem. If not, it is possibly a server configuration issue and not a problem with your computer.

Error code: ERR_TOO_MANY_REDIRECTS

If you have one of the following annotation,

@EnableWebSecurity
@EnableWebMvcSecurity

remove it to enable Spring Boot's Spring Security configuration

including the Spring Security filter.

See the following link for more detail.

http://izeye.blogspot.kr/2015/02/how-to-add-filter-after-spring-security.html

Change HTTP Basic authentication to form login in Spring Boot's Spring Security

To change HTTP Basic authentication to form login in Spring Boot's Spring Security,

add the following configuration:

@Configuration
@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}

How to add a filter after the Spring Security filter in Spring Boot

If you're using Spring Boot having a version after 1.2.0.RC1,

you can do it easily by setting the order of your filter any value above 0

because the order of the Spring Security Filter in Spring Boot is 0 by default.

But if you're using Spring boot having a version before 1.2.0.RC1,

you should register your own Spring Security filter

because the order of Spring Security Filter is Ordered.LOWEST_PRECEDENCE.

To use Spring Boot's Spring Security,

DO NOT use the following annotations:

@EnableWebSecurity
@EnableWebMvcSecurity

If you use either one,

SpringBootWebSecurityConfiguration is disabled as follows:

SpringBootWebSecurityConfiguration
      - @ConditionalOnClass classes found: org.springframework.security.config.annotation.web.configuration.EnableWebSecurity (OnClassCondition)
      - found web application StandardServletEnvironment (OnWebApplicationCondition)
      - @ConditionalOnMissingBean (types: org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration; SearchStrategy: all) found the following [org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration] (OnBeanCondition)

and WebSecurityConfiguration is activated.

So the order of Spring Security Filter will be Ordered.LOWEST_PRECEDENCE.

References:
https://github.com/spring-projects/spring-boot/issues/677
https://github.com/spring-projects/spring-boot/issues/1640
https://jira.spring.io/browse/SEC-2730
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-security