As the following helpful article (http://www.databasesandlife.com/hibernate-boolean-fields-mysql-50/) points out:
"There's a problem persisting boolean fields using Hibernate 3.2.2 to MySQL 5.0, if you allow Hibernate to generate your schema and you leave Hibernate to generate the schema in the default way". The problem is, by default, it generates a MqSQL field of type "bit(1)" - which causes Hibernate to throw:
could not insert: [com.company.MyObject] org.hibernate.exception.DataException: could not insert: [com.company.MyObject] at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:77) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43) .... Caused by: java.sql.SQLException: Data too long for column 'my_field' at row 1 at ....
When I try to save.
That's causing my tests to fail… so what to do?
Well the article I mention above suggests mapping the field using
<column sql-type="BOOLEAN" />,
which does work.
However, I'm using annotations, so my preferred mapping for booleans is:
@Column(columnDefinition = "tinyint", nullable = false)
private boolean exampleBooleanValue;
An alternative is to use:
@Column
private Boolean exampleBooleanValue;
But I prefer to work with primitives rather than boxed primitives wherever possible.
Anyway, the first solution above works wonderfully.
Saturday, October 25, 2008
Log4J Warnings
Annoyingly, when I run a junit test that is testing my Hibernate DAO objects, I get the following warnings:
log4j:WARN No appenders could be found for logger (jpt.dao.impl.test.GenericDaoImplTest). log4j:WARN Please initialize the log4j system properly.
This shouldn't be surprising, it's saying that Log4j hasn't been initialized properly. Why not? Well, It can't find my log4j.properties file. That's because hibernate needs it to be in the class path. So, I need to put log4j.properties into the classpath.
Well that's fine, and doing so does fix the problem - I just put log4j.properties into my src folder (or, in this case, specifically my test-src folder).
However, the problem is that I already have log4j.properties in the WebRoot/WEB-INF folder. When running my web-app (not the tests, but the web app itself), hibernate knows to look for it there because web.xml has:
<context-param>
<param-name>log4jConfigLocation</PARAM-NAME>
<param-value>/WEB-INF/log4j.properties</PARAM-VALUE>
</CONTEXT-PARAM>
What's more, that's exactly where I want my log4j.properties to be. Sure, I could change this to point somewhere else, but I don't want to do that. I want log4j.properties to be located in this directory for my web-app and configured just so.
So… the question is, how do I get Junit to initialize using this log4j.properties, rather than looking into src (on the classpath) and finding it missing. Well, I haven't been able to do it yet. I can manually configure log4j in my test class - but that's after the warnings are already shown. The only way I've been able to avoid those warnings is by placing log4j.properties into the classpath.
So, in the end, I've now got two versions of log4j.properties. One is in test-src and defines the logging levels etc for the debug running. One is in WebRoot/WEB-INF and defines logging levels for the webapp.
This is fine - and some might even say the best of both worlds - because I can have different default logging for my tests and my web-app. However, I still don't really like it. It could be confusing having two files named log4j.properites in the one project. What if I want to have only one!
Surely it shouldn't be THAT hard to configure my Junit test runs (that extend AbstractTransactionalDataSourceSprignContextTests) so that they search for the log4j.properties in the web-inf directory rather than on the classpath?!?!?!? Any ideas? (By the way, trying to add web-inf to the classpath doesn't work, as I'm using MyEclipse and it doesn't allow this!)
log4j:WARN No appenders could be found for logger (jpt.dao.impl.test.GenericDaoImplTest). log4j:WARN Please initialize the log4j system properly.
This shouldn't be surprising, it's saying that Log4j hasn't been initialized properly. Why not? Well, It can't find my log4j.properties file. That's because hibernate needs it to be in the class path. So, I need to put log4j.properties into the classpath.
Well that's fine, and doing so does fix the problem - I just put log4j.properties into my src folder (or, in this case, specifically my test-src folder).
However, the problem is that I already have log4j.properties in the WebRoot/WEB-INF folder. When running my web-app (not the tests, but the web app itself), hibernate knows to look for it there because web.xml has:
<context-param>
<param-name>log4jConfigLocation</PARAM-NAME>
<param-value>/WEB-INF/log4j.properties</PARAM-VALUE>
</CONTEXT-PARAM>
What's more, that's exactly where I want my log4j.properties to be. Sure, I could change this to point somewhere else, but I don't want to do that. I want log4j.properties to be located in this directory for my web-app and configured just so.
So… the question is, how do I get Junit to initialize using this log4j.properties, rather than looking into src (on the classpath) and finding it missing. Well, I haven't been able to do it yet. I can manually configure log4j in my test class - but that's after the warnings are already shown. The only way I've been able to avoid those warnings is by placing log4j.properties into the classpath.
So, in the end, I've now got two versions of log4j.properties. One is in test-src and defines the logging levels etc for the debug running. One is in WebRoot/WEB-INF and defines logging levels for the webapp.
This is fine - and some might even say the best of both worlds - because I can have different default logging for my tests and my web-app. However, I still don't really like it. It could be confusing having two files named log4j.properites in the one project. What if I want to have only one!
Surely it shouldn't be THAT hard to configure my Junit test runs (that extend AbstractTransactionalDataSourceSprignContextTests) so that they search for the log4j.properties in the web-inf directory rather than on the classpath?!?!?!? Any ideas? (By the way, trying to add web-inf to the classpath doesn't work, as I'm using MyEclipse and it doesn't allow this!)
Hibernate "PreInsertEvent.getSource()" NoSuchMethodError.
I recently obtained the following error:
java.lang.NoSuchMethodError: org.hibernate.event.PreInsertEvent.getSource()Lorg/hibernate/engine/SessionImplementor;
This occurred when attempting to run a test on one of my Hibernate DAO entities.
The problem started when I updated some (but not all) of my hibernate .jar libraries, to enable the use of spring-test.jar to provide access to the helper org.springframework.test.AbstractTransactionalDataSourceSpringContextTests methods.
It turns out (http://opensource.atlassian.com/projects/hibernate/browse/HV-67) that the problem was:
Method getSource from an older version of the Hibernate Core is referenced.
It is stated within the compatibility matrix that Hibernate Validator 3.1.0.CR1 is compatible only with Hibernate Core 3.3.x version(s).Exception in thread "main" java.lang.NoSuchMethodError: org.hibernate.event.PreInsertEvent.getSource()Lorg/hibernate/engine/SessionImplementor;
That is, I was using the latest Hibernate Core (3.3.x), but didn't have the most up to date Hibernate Validator. I downloaded a new hibernate-validator.jar and everything worked again.
java.lang.NoSuchMethodError: org.hibernate.event.PreInsertEvent.getSource()Lorg/hibernate/engine/SessionImplementor;
This occurred when attempting to run a test on one of my Hibernate DAO entities.
The problem started when I updated some (but not all) of my hibernate .jar libraries, to enable the use of spring-test.jar to provide access to the helper org.springframework.test.AbstractTransactionalDataSourceSpringContextTests methods.
It turns out (http://opensource.atlassian.com/projects/hibernate/browse/HV-67) that the problem was:
Method getSource from an older version of the Hibernate Core is referenced.
It is stated within the compatibility matrix that Hibernate Validator 3.1.0.CR1 is compatible only with Hibernate Core 3.3.x version(s).Exception in thread "main" java.lang.NoSuchMethodError: org.hibernate.event.PreInsertEvent.getSource()Lorg/hibernate/engine/SessionImplementor;
That is, I was using the latest Hibernate Core (3.3.x), but didn't have the most up to date Hibernate Validator. I downloaded a new hibernate-validator.jar and everything worked again.
Problems with @Test annotations with AbstractTransactionalDataSourceSpringContextTests.
I've recently been writing tests, most of which use the Junit @Test (http://junit.org/apidocs/org/junit/Test.html) annotations to identify the methods for testing as junit tests. This works really well, and also allows me to use other great annotations like @Before.
However I decided I needed to do some integration testing of my DAOs with the database. So, to do this, I took advantage of Spring's AbstractTransactionalDataSourceSpringContextTests class (http://static.springframework.org/spring/docs/2.0.x/api/index.html?org/springframework/test/AbstractTransactionalDataSourceSpringContextTests.html).
This is great, however, I noticed that all of my test annotations for classes extended AbstractTransactionalDataSourceSpringContextTests were being ignored. This means that tests that were named "testExample" would run, but those named "doTestExample" would not - even if annotated. More to the point, something called "testExample" would run as a test even if not annotated.
The reason soon became clear. AbstractTransactionalDataSourceSpringContextTests extends the Junit.Framework.TestCase class. Now JUnit4 and JUnit3 tests really should not be mixed and they don't go together. So, because I'm extending TestCase (although I don't really want to), I need to go back to old fashioned Junit Tests, without test annotations. This is commented, briefly in:
http://www.jetbrains.net/jira/browse/IDEA-16466
However I decided I needed to do some integration testing of my DAOs with the database. So, to do this, I took advantage of Spring's AbstractTransactionalDataSourceSpringContextTests class (http://static.springframework.org/spring/docs/2.0.x/api/index.html?org/springframework/test/AbstractTransactionalDataSourceSpringContextTests.html).
This is great, however, I noticed that all of my test annotations for classes extended AbstractTransactionalDataSourceSpringContextTests were being ignored. This means that tests that were named "testExample" would run, but those named "doTestExample" would not - even if annotated. More to the point, something called "testExample" would run as a test even if not annotated.
The reason soon became clear. AbstractTransactionalDataSourceSpringContextTests extends the Junit.Framework.TestCase class. Now JUnit4 and JUnit3 tests really should not be mixed and they don't go together. So, because I'm extending TestCase (although I don't really want to), I need to go back to old fashioned Junit Tests, without test annotations. This is commented, briefly in:
http://www.jetbrains.net/jira/browse/IDEA-16466
Tuesday, September 16, 2008
MySQL Database Recovery
I recently had a key application server die (hardware). One of the key applications running on this machine was a web-application that used a MySql database. We did have some specific MySql backup files, but the most recent backup of the data was a complete server backup of all files.
This meant that I had to work out how to restore a MySql database from the files stored in the data folder (under MySQL Server5.0/data/)
The files I had were:
ib_logfile0
ib_logfile1
ibdata1
and a folder, my_application, which contained a whole bunch of .frm files describing the table structures.
To restore MySql I started by copying these three files and one folder into a newly installed MySql folder on a replacement server. However, on starting mySql as a service, I got:
Could not start the MySQL service on Local Computer.
Error 1067: The process terminated unexpectedly.
I then checked out more information about this error in the file named machineName.err in the MySql/data folder.
This showed that:
InnoDB: Error: log file .\ib_logfile0 is of different size 0 25165824 bytes
InnoDB: than specified in the .cnf file 0 1782 57920 bytes.
080917 12:30:17 [ERROR] Default storage engine (InnoDB) is not available
080917 12:30:17 [ERROR] Aborting.
In this case, I went to my.ini file and changed:
innodb_log_file_size=170M
to
innodb_log_file_size=25165824
I was then able to start the MySql Server and create a normal backup for later retrieval on other servers.
This meant that I had to work out how to restore a MySql database from the files stored in the data folder (under MySQL Server5.0/data/)
The files I had were:
ib_logfile0
ib_logfile1
ibdata1
and a folder, my_application, which contained a whole bunch of .frm files describing the table structures.
To restore MySql I started by copying these three files and one folder into a newly installed MySql folder on a replacement server. However, on starting mySql as a service, I got:
Could not start the MySQL service on Local Computer.
Error 1067: The process terminated unexpectedly.
I then checked out more information about this error in the file named machineName.err in the MySql/data folder.
This showed that:
InnoDB: Error: log file .\ib_logfile0 is of different size 0 25165824 bytes
InnoDB: than specified in the .cnf file 0 1782 57920 bytes.
080917 12:30:17 [ERROR] Default storage engine (InnoDB) is not available
080917 12:30:17 [ERROR] Aborting.
In this case, I went to my.ini file and changed:
innodb_log_file_size=170M
to
innodb_log_file_size=25165824
I was then able to start the MySql Server and create a normal backup for later retrieval on other servers.
Sunday, September 14, 2008
Tomcat - Error starting.
I recently have been installing Tomcat 6 on a new server.
After installing a fresh JRE and then apache-tomcat-6.0.18.exe I got the error:
Windows could not start the Apache Tomcat on Local Computer. For more information, review the System Event Log. If this is a non-Microsoft service, contact the service vendor, and refer to service-specific error code 0.
To fix this I copied the file msvcr71.dll from my Java/bin directory into the Apache-Tomcat/bin directory.
It worked... though why it didn't work "out of the box" without such "black magic" I really don't know!!!!. I spent ages trying a range of different Tomcat installations, JAVA versions and classpath settings.
Aaaargh! Those were precious hours of my life I'm never going to get back...
After installing a fresh JRE and then apache-tomcat-6.0.18.exe I got the error:
Windows could not start the Apache Tomcat on Local Computer. For more information, review the System Event Log. If this is a non-Microsoft service, contact the service vendor, and refer to service-specific error code 0.
To fix this I copied the file msvcr71.dll from my Java/bin directory into the Apache-Tomcat/bin directory.
It worked... though why it didn't work "out of the box" without such "black magic" I really don't know!!!!. I spent ages trying a range of different Tomcat installations, JAVA versions and classpath settings.
Aaaargh! Those were precious hours of my life I'm never going to get back...
Wednesday, September 10, 2008
Upgrading Hibernate Annotations from V3.2 to V3.4.0
I recently blooged about a Hibernate Annotations bug that had been fixed in Hibernate Annotations 3.4.0, but not in 3.2.
While upgrading fixed this problem, I did have some problems with changing to Hibernate Annotations 3.4.
I tried downloading hibernate-annotations-3.4.0.GA.tar.gz and just swapping over the hibernate-annotations.jar file in my project. Seemed like a simple thing to do, however, using the new hibernate-annotations.jar file caused a new error:
Caused by: java.lang.NoClassDefFoundError: org/hibernate/annotations/common/reflection/ReflectionManager
This problem is discussed at this post. It turns out that, in upgrading, I need also to include hibernate-commons-annotations.jar.
Then I got another problem that is due to the lack of the slf4j-api.jar:
Caused by: java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
After that, I decided I'd better trust the README.txt file that comes with hibernate-annotations-3.4.0 and pulled across a bunch of (I think) required libraries:
dom4j.jar
ejb3-persistence.jar
hibernate-core.jar
slf4j-api.jar
slf4j-log4j12.jar
which fixed one problem... but led to another new error:
Caused by: java.lang.NoSuchFieldError: TRACE
The problem here seems to be that I need log4j.jar to be of version 1.2.12 or higher. (I've got 1.2.11 - missed it by that much!)
Having upgraded to log4j-1.2.15 that fixed that problem - but, a new one was waiting for me:
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/collections/map/LRUMapat org.hibernate.util.SimpleMRUCache.init(SimpleMRUCache.java:71)
I realized (following a bit of reading I probably should have done right at the start!) that I needed to upgrade not just the hibernate-annotations, but also the hibernate core packages themselves to be compatible with the new annotations.
I downloaded the hibernate-distribution-3.3.0.SP1-dist.tar.gz file (something I probably should have done right from the start).
With Hibernate and Hibernate Annotations both updated, everything worked just fine.
The Moral of the Story: Check the dependencies when you upgrade one part of a system and make sure you read the documentation!
Now... I won't make that mistake again (not a guarantee!)
While upgrading fixed this problem, I did have some problems with changing to Hibernate Annotations 3.4.
I tried downloading hibernate-annotations-3.4.0.GA.tar.gz and just swapping over the hibernate-annotations.jar file in my project. Seemed like a simple thing to do, however, using the new hibernate-annotations.jar file caused a new error:
Caused by: java.lang.NoClassDefFoundError: org/hibernate/annotations/common/reflection/ReflectionManager
This problem is discussed at this post. It turns out that, in upgrading, I need also to include hibernate-commons-annotations.jar.
Then I got another problem that is due to the lack of the slf4j-api.jar:
Caused by: java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
After that, I decided I'd better trust the README.txt file that comes with hibernate-annotations-3.4.0 and pulled across a bunch of (I think) required libraries:
dom4j.jar
ejb3-persistence.jar
hibernate-core.jar
slf4j-api.jar
slf4j-log4j12.jar
which fixed one problem... but led to another new error:
Caused by: java.lang.NoSuchFieldError: TRACE
The problem here seems to be that I need log4j.jar to be of version 1.2.12 or higher. (I've got 1.2.11 - missed it by that much!)
Having upgraded to log4j-1.2.15 that fixed that problem - but, a new one was waiting for me:
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/collections/map/LRUMapat org.hibernate.util.SimpleMRUCache.init(SimpleMRUCache.java:71)
I realized (following a bit of reading I probably should have done right at the start!) that I needed to upgrade not just the hibernate-annotations, but also the hibernate core packages themselves to be compatible with the new annotations.
I downloaded the hibernate-distribution-3.3.0.SP1-dist.tar.gz file (something I probably should have done right from the start).
With Hibernate and Hibernate Annotations both updated, everything worked just fine.
The Moral of the Story: Check the dependencies when you upgrade one part of a system and make sure you read the documentation!
Now... I won't make that mistake again (not a guarantee!)
Subscribe to:
Posts (Atom)