I recently needed to create an XML Schema XSD file from an existing XML file. A short research pointed me to Trang. Description from their website:
Trang, a program for converting between different schema languages, focused on RELAX NG; in particular, it can convert between the compact and XML syntaxes, it can convert between RELAX NG and DTDs, and it can convert from RELAX NG to W3C XML Schema
But beside the convertion between different schema languages, Trang is also able to create schemas based on XML files.
The creation of an XSD is done as follows for UTF-8 encoding using a JRE 1.5 or above:
My new employer uses Subversion as the central
version control system, so I'm trying to take the first steps as my former employer
still used the good old CVS. (This also means that you don't find advanced infos
here but only novice infos.)
So, how to import an existing project to Subversion? I don't mind loosing the
history of the project, of course this makes the whole migration process a lot easier.
1. Create a Subversion repository
First, a central Subversion repository has to be created if it does not exist already:
$ svnadmin create /svn/repos
2. Import an existing project to the trunk
So, let's import the project directory myproject to Subversion. I already
learned that the recommended structure should be as follows:
myproject/
trunk/
tags/
branches/
As in a non-Subversion project, the trunk, tags and branches directories
usually do not exist yet, they have to be created first. The import sequence for the project directory myproject becomes as follows:
$ cd <parent directory of the project directory myproject>
$ mkdir myproject_svn myproject_svn/tags myproject_svn/branches
$ mv myproject myproject_svn/trunk
$ svn import myproject_svn file:///svn/repos/myproject
As the Subversion repository is locally visible, I use the file:// schema.
Don't forget to add myproject to the last command or all files in svn_myproject
will be imported directly into the root directory of the repository.
You cannot work directly with the created myproject_svn directory above,
you first have to checkout it again:
$ cd myproject
$ svn copy trunk/ branches/myproject-branch
$ svn status
A + branches/myproject-branch
Here, the trunk/ directory is copied recursively in the working
directory brances/myproject-branch. The output of the command svn status
indicates that the directory is ready to be added to the repository.
The + says that branches/myproject-branch is just a copy and nothing new.
When commiting, Subversion creates the directory in the repository:
Subversion does not really copy all files, but just creates a new repository
entry pointing to the original tree, so this is also called a “cheap copy”.
Please refer to the Subversion documentation for more detailed infos.
The one step method without the need of a temporary directory is as follows:
$ svn copy file:///svn/repos/myproject-trunk \
file:///svn/repos/myproject/branches/myproject-branch \
-m"creating new branch"
Now, if you are in the Java context, then type "logger" followed by "Ctrl+space". You are invited to choose from different templates including your template entered above:
After choosing the template, you ending up with an added logger plus the corresponding Java import:
Reading and writing UTC timestamps to a database when the default timezone may change. E.g., this might happen in an application server if an application running in the same JRE changes the default timezone as follows:
The easiest solution to solve this problem I know is to create an own mapping type extending the standard Hibernate timestamp type org.hibernate.type.TimestampType:
packagech.meteoswiss.commons.hibernate;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Timestamp;importjava.util.Calendar;importjava.util.SimpleTimeZone;/**
* <tt>Timestamp</tt>: A type that maps an SQL TIMESTAMP to a Java
* java.util.Date or java.sql.Timestamp using UTC time zone.
*/publicclassUTCTimestampTypeextendsorg.hibernate.type.TimestampType{@OverridepublicObjectget(ResultSetrs,Stringname)throwsSQLException{returnrs.getTimestamp(name,createUTCCalendar());}/**
* Creates UTC calendar. DO NOT USE a static calendar instance.
* This may lead to concurrency problems with (at least) the Oracle DB
* driver!
* @return Calendar with UTC time zone.
*/privatestaticCalendarcreateUTCCalendar(){finalCalendarc=Calendar.getInstance();c.setTimeZone(newSimpleTimeZone(0,"UTC"));returnc;}@Overridepublicvoidset(PreparedStatementst,Objectvalue,intindex)throwsSQLException{Timestampts;if(valueinstanceofTimestamp){ts=(Timestamp)value;}else{ts=newTimestamp(((java.util.Date)value).getTime());}st.setTimestamp(index,ts,createUTCCalendar());}}
Use it as follows with Java annotations (you could use the type class also
in a XML configuration file):
The V_ in the table name indicates that this is a Oracle view and not a table.
This name follows our naming conventions. As the name of the view indicates,
the view is holding all information about measurement sites (I actually work
for the national weather service). This table is mapped to the following Java class:
@Entity(table="V_MEAS_SITE")publicclassMeasurementSite{@Id@Column(name="MEAS_SITE_ID")privateintmeasurementSiteId;@Column(name="INSTALLATION_ID")privateintinstallationId;@Column(name="NAME_TX")privateStringname;// getter/setter are ommited for brevit@OverridpublicinthashCode(){finalintprime=31;intresult=1;return=prime*result+((getMeasurementSiteId()==null)?0:getMeasurementSiteId().hashCode());}@Overridpublicbooleanequals(Objectobj){if(this==obj){returntrue;}if(obj==null){returnfalse;}if(!(objinstanceofMeasurementSite)){returnfalse;}MeasurementSiteother=(MeasurementSite)obj;if(installationId==null){if(other.getInstallationId()!=null){returnfalse;}}elseif(!getMeasurementSiteId().equals(other.getMeasurementSiteId())){returnfalse;}returntrue;}}
Let's write an EJB session bean reading some data:
@SessionpublicclassMeasurementSiteServiceimplementsMeasurementSiteLocal{@PersistenceContext(unitName="DefaultEntityManager")privateEntityManagerem;publicList<MeasurementSite>findByName(Stringname){Stringsql="select m from MeasurementSite where m.name like :name";returnem.createQuery(sql).setParameter("name",name).list();}// used for testingpublicvoidsetEntityManager(EntityManagerem){this.em=em;}}
That's easy. OK, let's test this mapping with a JUnit test class:
publicclassMeasurementSiteServiceTest{privateEntityManagerem=....;// set up the entity manager @TestpublicvoidfindByName()MeasurementSiteServices=newMeasurementSiteService();s.setEntityManager(em);List<MeasurementSite>list=s.findByName("Z%");for(MeasurementSitem:list){Assert.notNull(m);}}}
However, this test fails. There are indeed some NULL entity entries in the list.
Hibernate must be broken! Of course, Hibernate is not broken. Do you see what went wrong?
I did after some time of debugging. The view catches content of different tables and is
therefore de-normalized. The primary key of the V_MEAS_SITE view is not MEAS_SITE_ID
but INSTALLATION_ID!
As a view has no explicit contraints there is no primary key constraint neither and therefore
you have no explicit indications about the "logic" in the data. In this case it means that
there are more than one entry for a given measurement site ID. And that's why Hibernate
returned the NULL values.
Of course it would be nice, if Hibernate had thrown some Exceptions to help
a careless Java developer...
By the way, Oracle DB allows to query the DLL statement: