Tuesday, June 30, 2015

`spring.data.rest.base-uri` doesn't work

After Spring Boot 1.3.0.M1, the following property doesn't work:

spring.data.rest.base-uri=/api

You have to use the following property:

spring.data.rest.base-path=/api

This is corresponding to Spring Data REST change.

Monday, June 29, 2015

Handle keys having dots in JsonPath

When you handle keys having dots in JsonPath,

you can use one of the followings:

// NOTE: 1L doesn't work. Why?
assertThat(JsonPath.<Long> read(metrics, "['counter.test']"), is(1));
assertThat(JsonPath.<Long> read(metrics, "$['counter.test']"), is(1));
assertThat(JsonPath.<Long> read(metrics, "$.['counter.test']"), is(1));

I'm not sure why `<Long>` doesn't work as expected.

It's converted into `Integer`.

You can see a sample in the following:

https://github.com/izeye/samples-spring-boot-branches/blob/rest-and-actuator/src/test/java/samples/springboot/counter/web/CounterControllerTests.java

Reference:
http://stackoverflow.com/questions/19726859/jsonpath-junit-escape-character-for-dots

Get detailed stack traces of failed tests in Gradle

When a test failed in Gradle,

you will get the following stack trace:

com.izeye.test.SomeTests > test FAILED
    java.lang.IllegalStateException                                                    
        Caused by: org.springframework.beans.factory.BeanCreationException              
            Caused by: java.lang.NoClassDefFoundError                                  
                Caused by: java.lang.ClassNotFoundException

But it's sometimes not useful.

When you want to get a detailed stack trace,

add the following configuration:

    test {
        testLogging {
            exceptionFormat = 'full'
        }
    }

Now you will get the following output:

com.izeye.test.SomeTests > test FAILED  
    java.lang.IllegalStateException: Failed to load ApplicationContext                  
                                                                                       
        Caused by:                                                                      
        org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [com/izeye/test/config/PersistenceConfig.class]: Invocation of init method failed; nested exception is java.lang.NoClassDefF
oundError: org/w3c/dom/ElementTraversal
                                                                                       
            Caused by:                                                                  
            java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal                
                                                                                       
                Caused by:                                                              
                java.lang.ClassNotFoundException: org.w3c.dom.ElementTraversal      

Now you can see that the culprit was `org.w3c.dom.ElementTraversal `.

Reference:
http://java.dzone.com/articles/gradle-goodness-show-more

Caused by: java.lang.NoSuchFieldException: $jacocoAccess

When you run the following command:

gradle clean test

you might get the following exception:

Caused by: java.lang.NoSuchFieldException: $jacocoAccess

JaCoCo default version (0.6.2.201302030002) doesn't work with Java 8.

You can check your JaCoCo version with the following configuration:

    jacoco {
        println toolVersion
    }

and you will get the following output:

0.6.2.201302030002

You can fix with the following configuration:

    jacoco {
        toolVersion = "0.7.1.201405082137"
    }

Reference:
https://github.com/jacoco/jacoco/issues/74

Missing `datasource.xxx.active` and `datasource.xxx.usage` in `metrics` endpoint in Spring Boot Actuator

In Spring Boot Actuator's `metrics` endpoint,

if you can't see `datasource.xxx.active` and `datasource.xxx.usage`,

you might have the following configuration:

@SpringBootApplication(exclude = {
    DataSourceAutoConfiguration.class,
    DataSourceTransactionManagerAutoConfiguration.class
})

Showing the metrics needs `DataSourcePoolMetadataProvidersConfiguration`

which is included in `DataSourceAutoConfiguration`.

So you have to use the following if you don't use `DataSourceAutoConfiguration`:

@Import(DataSourcePoolMetadataProvidersConfiguration.class)

It would be nice to separate them because `DataSourceAutoConfiguration` doesn't work

when having multiple `DataSource`s.

Friday, June 26, 2015

`java.lang.StackOverflowError` in Spring Data MongoDB

You might encounter the following error suddenly:

java.lang.StackOverflowError
at java.lang.String.<init>(String.java:201)
at java.lang.String.substring(String.java:1956)
at sun.reflect.misc.ReflectUtil.isNonPublicProxyClass(ReflectUtil.java:288)
at sun.reflect.misc.ReflectUtil.checkPackageAccess(ReflectUtil.java:165)
at sun.reflect.misc.ReflectUtil.isPackageAccessible(ReflectUtil.java:195)
at java.beans.MethodRef.get(MethodRef.java:72)
at java.beans.PropertyDescriptor.getReadMethod(PropertyDescriptor.java:206)
at org.springframework.data.mapping.model.AbstractPersistentProperty.getGetter(AbstractPersistentProperty.java:159)
at org.springframework.data.mapping.model.BeanWrapper.getProperty(BeanWrapper.java:127)
at org.springframework.data.mapping.model.BeanWrapper.getProperty(BeanWrapper.java:100)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$3.doWithPersistentProperty(MappingMongoConverter.java:419)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$3.doWithPersistentProperty(MappingMongoConverter.java:412)
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:307)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:412)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:386)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeCollectionInternal(MappingMongoConverter.java:622)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.createCollection(MappingMongoConverter.java:546)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writePropertyInternal(MappingMongoConverter.java:457)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$3.doWithPersistentProperty(MappingMongoConverter.java:424)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$3.doWithPersistentProperty(MappingMongoConverter.java:412)
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:307)

I didn't dig into the problem due to lack of time

but the culprit was `Logger` in a MongoDB document as follows:

  private final Logger log = LoggerFactory.getLogger(getClass());

It could be fixed with `org.springframework.data.annotation.Transient` as follows:

  @Transient
  private final Logger log = LoggerFactory.getLogger(getClass());

but it doesn't make sense that every document has its own field for the logger

although the logger will be singleton.

Using `static` is much better as follows:

  private static final Logger log = LoggerFactory.getLogger(NaboxImpressionLog.class);

Reference:
http://stackoverflow.com/questions/21734785/mongodb-spring-saving-an-object-causes-stackoverflowerror

Sunday, June 21, 2015

Error:Cause: net.rubygrapefruit.platform.internal.jni.WindowsHandleFunctions.markStandardHandlesUninheritable(Lnet/rubygrapefruit/platform/internal/FunctionResult;)V

I encountered the following error in IntelliJ when I tried to run a Gradle task:

Error:Cause: net.rubygrapefruit.platform.internal.jni.WindowsHandleFunctions.markStandardHandlesUninheritable(Lnet/rubygrapefruit/platform/internal/FunctionResult;)V

I can run a Gradle task in a terminal but I can't run a Gradle task in IntelliJ any more.

I'll update if I find any.

Any hint to solve this problem will be appreciatied.

---

UPDATED:

Restarting IntelliJ solved the problem :-)

Wednesday, June 17, 2015

java.lang.IllegalArgumentException: Cannot locate declared field class org.apache.http.impl.client.HttpClientBuilder.sslcontext

When you try to use `HtmlUnit`,

you might encounter the following exception:

java.lang.IllegalArgumentException: Cannot locate declared field class org.apache.http.impl.client.HttpClientBuilder.sslcontext

You're using httpcomponents 4.5.

If you don't need the version,

downgrade it to 4.4.1 as follows:

    testCompile("org.apache.httpcomponents:httpclient:4.4.1")
    testCompile("org.apache.httpcomponents:httpmime:4.4.1")

References:
http://htmlunit.10904.n7.nabble.com/HtmlUnit-htmlunit-bugs-1692-Update-to-HttpComponents-4-5-td36318.html

Tuesday, June 16, 2015

Show all indexes in MongoDB

To show all indexes in MongoDB,

you can use the following command:

db.someCollection.getIndexes()

Reference:
http://docs.mongodb.org/manual/tutorial/list-indexes/

Relocate MongoDB storage location in CentOS

To relocate MongoDB storage location in CentOS,

stop MongoDB server with the following command:

sudo /sbin/service mongod stop

Modify MongoDB configuration as follows:

sudo vi /etc/mongod.conf

#dbpath=/var/lib/mongo
dbpath=/home/izeye/mongo

Start MongoDB server with the following command:

sudo /sbin/service mongod start

Note that the directory should be owned by `mongod` user.

If not, change it by the following command:

sudo chown mongod /home/izeye/mongo/

Caused by: com.mongodb.WriteConcernException: { "serverUsed" : "1.2.3.4:27017" , "ok" : 1 , "n" : 0 , "err" : "new file allocation failure" , "code" : 12520}

You might encounter the following exception:

Caused by: com.mongodb.WriteConcernException: { "serverUsed" : "1.2.3.4:27017" , "ok" : 1 , "n" : 0 , "err" : "new file allocation failure" , "code" : 12520}

You can check your MongoDB server log with the following command:

sudo vi /var/log/mongodb/mongod.log

The log will have the following lines:

2015-06-10T20:19:19.311+0900 I -        [conn7] Assertion: 12520:new file allocation failure
2015-06-10T20:19:19.313+0900 I STORAGE  [FileAllocator] allocating new datafile /var/lib/mongo/test.6, filling with zeroes...
2015-06-10T20:19:19.316+0900 I -        [conn7] Assertion: 12520:new file allocation failure
2015-06-10T20:19:19.316+0900 I STORAGE  [FileAllocator] FileAllocator: posix_fallocate failed: errno:28 No space left on device falling back
2015-06-10T20:19:19.317+0900 I STORAGE  [FileAllocator] error: failed to allocate new file: /var/lib/mongo/test.6 size: 2146435072 failure creating new datafile; lseek failed for fd 22 with errno: errno:2 No such file or directory.  will try again in 10 seconds
2015-06-10T20:19:19.322+0900 I -        [conn7] Assertion: 12520:new file allocation failure

You can notice there is not enough space.

So you can clean up your disk

or relocate MongoDB storage location

to a directory mounted on a different partition or disk.

Sunday, June 14, 2015

Caused by: java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal

You can encounter the following error after upgrading to Spring Boot 1.3.0.M1:

Caused by: java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:455)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:367)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.apache.xerces.parsers.AbstractDOMParser.startDocument(Unknown Source)
at org.apache.xerces.impl.dtd.XMLDTDValidator.startDocument(Unknown Source)
at org.apache.xerces.impl.XMLDocumentScannerImpl.startEntity(Unknown Source)
at org.apache.xerces.impl.XMLVersionDetector.startDocumentParsing(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at org.apache.ibatis.parsing.XPathParser.createDocument(XPathParser.java:254)
at org.apache.ibatis.parsing.XPathParser.<init>(XPathParser.java:125)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.<init>(XMLConfigBuilder.java:75)
at org.mybatis.spring.SqlSessionFactoryBean.buildSqlSessionFactory(SqlSessionFactoryBean.java:358)
at org.mybatis.spring.SqlSessionFactoryBean.afterPropertiesSet(SqlSessionFactoryBean.java:340)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)

With the hint from StackOverflow and the following command:

gradle dependencies

I can figure out that `xml-apis-1.4.01` has been changed to `xml-apis-1.3.04` as follows:

Before upgrading to Spring Boot 1.3.0.M1:

+--- net.sourceforge.nekohtml:nekohtml:1.9.22
|    \--- xerces:xercesImpl:2.11.0
|         \--- xml-apis:xml-apis:1.4.01

After upgrading to Spring Boot 1.3.0.M1:

+--- net.sourceforge.nekohtml:nekohtml:1.9.22
|    \--- xerces:xercesImpl:2.11.0
|         \--- xml-apis:xml-apis:1.4.01 -> 1.3.04

With the following command:

gradle dependencyInsight --dependency xml-apis

you will get the following result:

:dependencyInsight                                                                                                                                              
xml-apis:xml-apis:1.3.04 (selected by rule)
                                 
xml-apis:xml-apis:1.4.01 -> 1.3.04
\--- xerces:xercesImpl:2.11.0    
     \--- net.sourceforge.nekohtml:nekohtml:1.9.22
          \--- compile

`spring-boot-dependencies` enforces `1.3.04` as follows:

<xml-apis.version>1.3.04</xml-apis.version>

You can resolve the problem by using `xml-apis:1.4.01` as follows:

compile("xml-apis:xml-apis:1.4.01")

I created a PR to upgrade `xml-apis as follows:

https://github.com/spring-projects/spring-boot/pull/3226

References:
http://stackoverflow.com/questions/10234201/appengine-error-java-lang-noclassdeffounderror-org-w3c-dom-elementtraversal
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-dependencies/pom.xml

Friday, June 12, 2015

Error creating bean with name 'mbeanExporter' defined in class path resource [org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.class]

When you have the following JMX configuration with Spring Boot,

  @Bean
  public MBeanServerFactoryBean mBeanServer() {
    MBeanServerFactoryBean mBeanServerFactoryBean = new MBeanServerFactoryBean();
    mBeanServerFactoryBean.setLocateExistingServerIfPossible(true);
    return mBeanServerFactoryBean;
  }

you can encounter the following exception:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mbeanExporter' defined in class path resource [org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.jmx.export.annotation.AnnotationMBeanExporter]: Factory method 'mbeanExporter' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'mbeanServer' is defined
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1119)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1014)

If you should keep your own `MBeanServer`,

set the following property in `application.properties`:

spring.jmx.server=mBeanServer

If you don't have to keep your own `MBeanServer`,

drop your own JMX configuration for `MBeanServer`

and use one provided by Spring Boot.

Reference:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/

Thursday, June 11, 2015

List all indexes in MongoDB

To list all indexes in MongoDB,

you can do the following:

> db.someCollection.getIndexes()                                                                                
[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "test.someCollection"
        },
        {
                "v" : 1,
                "key" : {
                        "someIndexProperty" : 1
                },
                "name" : "someIndexProperty_1",
                "ns" : "test.someCollection"
        }
]
>

Reference:
http://docs.mongodb.org/manual/tutorial/list-indexes/

Create an index in MongoDB

To create an index in MongoDB,

you can do the following:

> db.someCollection.createIndex({someIndexProperty: 1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
>

Reference:
http://docs.mongodb.org/manual/tutorial/create-an-index/

Tuesday, June 9, 2015

Oracle VARCHAR2's length is BYTE or CHAR?

Oracle VARCHAR2's length is BYTE or CHAR?

It depends on an option you used when creating a column as follows:

VARCHAR2(20 BYTE)

VARCHAR2(20 CHAR)

What if you omit the option as follows?

VARCHAR2(20)

It depends on the global setting for length semantics.

You can check the setting as follows:

SELECT VALUE FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER = 'NLS_LENGTH_SEMANTICS';

BYTE

References:
http://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#CNCPT1824
http://oracleschools.blogspot.kr/2013/01/how-to-check-nlslengthsemantics.html

How to use `sort` in Spring Data REST

To use `sort` in Spring Data REST,

you can use as follows:

http://localhost:{port}/api/customers?sort=firstName,desc

You can reference the following sample project:

https://github.com/izeye/samples-spring-boot-branches/tree/jpa-and-data-rest

Reference:
http://docs.spring.io/spring-data/rest/docs/current/reference/html/

Monday, June 8, 2015

MongoDB installation location in Windows

MongoDB installation location in Windows is as follows:

C:\Program Files\MongoDB\Server\3.0\bin

Allow all interfaces to listen for MongoDB in CentOS 6.6

To allow all interfaces to listen for MongoDB in CentOS 6.6,

comment out the `bind_ip` as follows:

sudo vi /etc/mongod.conf

# Listen to local interface only. Comment out to listen on all interfaces.
#bind_ip=127.0.0.1

Restart the MongoDB server (mongod) as follows:

sudo /sbin/service mongod start

Change MongoDB server port in CentOS 6.6

To change MongoDB server port in CentOS 6.6,

edit the following configuration:

sudo vi /etc/mongod.conf

port=10000

Restart the MongoDB server (mongod) as follows:

sudo /sbin/service mongod start

Reference:
http://docs.mongodb.org/manual/reference/configuration-options/

Install MongoDB on CentOS 6.6

To install MongoDB on CentOS 6.6,

you add MongoDB repository as follows:

sudo vi /etc/yum.repos.d/mongodb-org-3.0.repo

[mongodb-org-3.0]
name=MongoDB Repository
baseurl=http://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.0/x86_64/
gpgcheck=0
enabled=1

Install MongoDB by `yum` as follows:

sudo yum install -y mongodb-org

Start MongoDB by `service` as follows:

sudo /sbin/service mongod start

Check listening port as follows:

sudo vi /var/log/mongodb/mongod.log

2015-06-08T21:14:23.908+0900 I NETWORK  [initandlisten] waiting for connections on port 27017

Run MongoDB client as follows:

mongo

Reference:
http://docs.mongodb.org/manual/tutorial/install-mongodb-on-red-hat/

java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy52

When you are using Spring Data MongoDB,

you can encounter the following exception:

Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy52
at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)

It happened by adding `@Repository` accidentally as follows:

@Repository
public interface SomethingRepository extends MongoRepository<Something, String> {
}

Removing `@Repository` fixes the problem.

It would be better to have an exception having better explanation if possible.

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

Hotfix KB2731284 or later update is not installed, will zero-out data files

When you run a MongoDB server (mongod) in Windows,

you can encounter the following error:

C:\Program Files\MongoDB\Server\3.0\bin>mongod
2015-06-08T20:29:47.485+0900 I CONTROL  Hotfix KB2731284 or later update is not installed, will zero-out data files
2015-06-08T20:29:47.565+0900 I STORAGE  [initandlisten] exception in initAndListen: 29 Data directory C:\data\db\ not found., terminating
2015-06-08T20:29:47.565+0900 I CONTROL  [initandlisten] dbexit:  rc: 100

You can fix it by creating the following directory:

C:\data\db

Unfortunately I can't understand why it fixed the problem.

Anyone who explains why?

Reference:
http://stackoverflow.com/questions/29316482/mongo-error-on-i-control-hotfix

Saturday, June 6, 2015

Show all sub-projects' dependencies in Gradle

In Gradle, to show all sub-projects' dependencies,

add the following to `build.gradle`.

subprojects {
    task allDependencies(type: DependencyReportTask) {}
}

Now you can use the following command:

gradle allDependencies

Reference:
https://solidsoft.wordpress.com/2014/11/13/gradle-tricks-display-dependencies-for-all-subprojects-in-multi-project-build/

Caused by: java.lang.NoSuchMethodError: org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry.hasMappingForPattern(Ljava/lang/String;)Z

You can encounter the following error:

Caused by: java.lang.NoSuchMethodError: org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry.hasMappingForPattern(Ljava/lang/String;)Z
at org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.addResourceHandlers(WebMvcAutoConfiguration.java:256)
at org.springframework.web.servlet.config.annotation.WebMvcConfigurerComposite.addResourceHandlers(WebMvcConfigurerComposite.java:102)

Using `gradle dependencies` didn't help me much.

It showed the right dependency I expected:

org.springframework:spring-webmvc:4.1.6.RELEASE

It's one of Gradle sub-projects.

It is caused by another sub-project which it depends on.

The sub-project has a dependency having the following transitive dependency:

org.springframework.mobile:spring-mobile-device:1.1.3.RELEASE

And it has the following transitive dependency:

org.springframework:spring-webmvc:3.2.11.RELEASE

So the conflict occurred.

I solved it as follows:

    compile("xxx:xxx:1.0.0") {
        exclude module: 'spring-mobile-device'
    }

But I can't understand why the latest dependency doesn't win.

Tuesday, June 2, 2015

Show disk usages of all directories in Windows

If you want to know disk usages of all directories in Windows,

you can use `WinDirStat`.

I used it to find directories using a lot of space and it nicely worked.

Reference:
http://windirstat.info/