[255062 views]

[]

Odi's astoundingly incomplete notes

New entries

Code

back | next

JDK nio Bug

It's once a year or so that I find a bug in the Java library. This time it's in the java.nio.Channels.newChannel method. It contains a buggy check for a class name:
String inClass = in.getClass().toString();
if (inClass.equals("java.io.FileInputStream"))
This test will never succeed because toString does not return the class name. They should have used getClass().getName() instead. It's not a very bad bug, but it prevents some optimizations with FileChannels.

By the way, most sample code on the net for copying data with nio is wrong. The following is the correct way of doing it. The crux is that the read and write method may not read/write all of the buffer!
java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate(bufsize);
buffer.clear();
// the loop is safe for partial reads and writes
while (in.read(buffer) >= 0 || buffer.position() > 0) {
  buffer.flip();
  out.write(buffer);
  buffer.compact();
}
Similar with transferTo/From:
FileChannel fc = ...
long len = fc.size();
long pos = 0L;
while (pos < len) {
  pos += fc.transferTo(pos, len, outch);
}
FileChannel fc = ...
long len = fc.size();
long pos = 0L;
while (pos < len) {
  pos += fc.transferFrom(inch, pos, len);
}

posted on 2007-01-25 11:42 UTC in Code | 1 comments | permalink
Alegedly fixed in 1.6

Oracle: convert LONG to VARCHAR

Seems hard, but is simple (at least with 10g):
mystring := substr(mylong, 1);
With older Oracle versions your milage may vary.

posted on 2006-11-30 13:57 UTC in Code | 1 comments | permalink
This only seems to work in PLSQL. A SQL variant still eludes me...

Todd Brook

Making JSP content assist work in Eclipse

Eclipse has had nice HTML, JavaScript and JSP editor for a while now. They are part of the J2EE Standard Tools (JST) of the Web Tools Platform (WTP). When I create webapps I usually have the JSP pages in a WAR-like directory structure. This way I can point a Tomcat Context directly to this directory.
src
 +- java-webapps
     +- app1
          +- index.jsp
          +- WEB-INF
            +- jsp
            |   +- home.jsp
            |   +- form.jsp
            |
            +- lib
            |   +- taglibs-input-1.0.jar
            |   +- taglibs-standard-1.1.2.jar
            |   +- spring-1.2.8.jar
            +- web.xml
            +- spring-servlet.xml
            +- applicationContext.xml
If in the JSP editor you get warning marks on all tags from a taglib, then you need to put the taglib JARs into the WEB-INF/lib directory. It's not enough to have them in the classpath! It looks like the editor somehow recognizes the WAR structure and tries to get the libraries from it.

posted on 2006-10-11 10:10 UTC in Code | 0 comments | permalink

Source code management best practices

One of the best articles about this topic I have ever read. Once again it's speaking deeply from my heart.

posted on 2006-09-28 10:48 UTC in Code | 0 comments | permalink

Diffing by date on a CVS branch

I wanted to compare my current working copy of a CVS branch to a previous version by date. I had to discover that Eclipse does not provide this possibility: you can specify CVS revisions by date, but only on CVS HEAD. So I had no other choice but do this from the command line:
cvs co -r BRANCH_abc -D '2006-09-25 12:25' mymodule
cvs diff -r BRANCH_abc

posted on 2006-09-28 10:30 UTC in Code | 1 comments | permalink
Thanks, I found this out the hard way too.

- Mike

Import an oracle dump into any tablespace

Oracle is a great DB. But when it comes to tablespaces its management features suck. There is no easy way to move all objects (tables, indexes, sequences, LOBs etc.) between tablespaces at once for instance. (You need to generate SQL for every object type.) Another big problem is when you move data with export / import between different DB instances. Usually tablespace names are completely different between different DB instances. But Oracle's imp utility does not directly support import into a tablespace of a different name. So you have to do some nasty workaround:
  1. Use the imp utility's INDEXFILE= option to create a script.
  2. Edit this script: remove the REM from the CREATE TABLE statetments, get rid of the spurious "... 123 rows", replace all TABLESPACE XXX clauses with the appropriate ones, replace all schema names with yours if necessary.
  3. Run this script to create the empty schema.
  4. Disable all constraints.
  5. Remove the UNLIMITED_TABLESPACE privilege from the user.
  6. Give the user unlimited table space quota on the tablespaces you want.
  7. Import the dump with IGNORE=y and FROMUSER and TOUSER options if necessary.
  8. Enable all constraints.
  9. Revert your tablespace quota settings.
If space allows you can alternatively create a new tablespace with the same name as in the export DB. Then import the dump. Then you can move all objects. To get the necessary statements you can execute:
SELECT 'ALTER TABLE '|| table_name ||' MOVE TABLESPACE USERS;' 
FROM user_tables WHERE tablespace_name='xxx';

SELECT 'ALTER INDEX '|| index_name ||' REBUILD TABLESPACE USERS;'
 FROM user_indexes WHERE tablespace_name='xxx';

SELECT 'ALTER TABLE '|| table_name ||' MOVE LOB ('
|| column_name ||') STORE AS (TABLESPACE USERS);'
FROM user_lobs WHERE tablespace_name='xxx';
Execute the generated statements. After that the new tablespace should be empty and can be removed again.
posted on 2006-09-22 17:45 UTC in Code | 0 comments | permalink

Copy to an SMB share

Here is how to copy a file from a Linux machine to a remote Windows share without mounting. It uses the smbclient:
smbclient '\\host\share' password -D 'the/directory' \
-U username -c 'put myfile.txt'
Or if you like it more secure, use an auth file:
cat smb.auth
username = marvin
password = valium
domain = galaxy
smbclient '\\host\share' -D 'the/directory' \
-A smb.auth -c 'put myfile.txt'


posted on 2006-09-15 09:59 UTC in Code | 0 comments | permalink

Cloneable does not supersede the copy constructor

Common misconception: "Copy constructors are a relic from the C++ ages. In Java we have the Cloneable interface."

The clone method is handy when one has an object of an unknown (sub)class and you need a copy. You will most likely end up with an object of the same class. Consider the following scenario: You have a business object and you need to "split" it. So you need to copy parts of this structure. Some of the objects will be of a subtype of the declared field. So only their clone method can correctly perform the copy.

The copy constructor is much more type-safe. You know exactly which class you create and its constructor accepts an object of a well-known class. A copy constructor for example allows you do "downcast" an object. Consider the following scenario: You have an object of the last final class in a class hierarchy. Now you have to pass this object on to an XML serialization but you only want fields of a superclass to be serialized. A copy constructor of that superclass will solve the problem.

A variant of the copy constructor is the template pattern. In the template pattern the copy constructor accepts a template object of a superclass to initialize its state.


posted on 2006-06-29 17:55 UTC in Code | 0 comments | permalink

Future desktop interaction

There is a nice video about how future interaction with your PC's desktop may look like. What seems fancy and amazing to you, may feel very natural for your kids.

posted on 2006-06-24 07:41 UTC in Code | 0 comments | permalink

Today's code hilight

Sometimes my co hackers are just brilliant:
log.debug("");

posted on 2006-06-01 18:11 UTC in Code | 0 comments | permalink
back | next