Donnerstag, 17. Dezember 2009

Printer is not accepting job

As a Java programmer you might have experienced this message already. And I bet, you were not happy with it.

You'll see it, e.g. if the printer has been turned off and the windows spooler treats the printer as offline.
Which is not that bad, as the spooler itself is still capable to receive print jobs and queue them until the printer is online again.

But not so Java. Java simply ignores the fact that the queue is still accepting jobs - even with JRE 1.6.0_17.

Probably someone mixed up the terms Printer and Queue. If - and only if - the queue is not accepting jobs, Java is allowed to throw an exception.
I am not sure if Windows allows to disable the Queue, the *nix spooler CUPS definitely does.
But actually, Java denies printing even if the Queue is online.

Long story short: If you can afford not having the PrinterIsAcceptingJobs status available in your program - what should be no problem, the following solution is for you.
The solution acutally is just for the Win32 printer service, but should be easily extendable for the *nix one - if you have problems there too.

You need:
  • A Java compiler
  • javassist
And this helper class:

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import sun.print.Win32PrintService;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;

public class Win32PrintServiceFixer
{
 public static void main(String[] args) throws Exception
 {
  ClassPool pool = ClassPool.getDefault();
  instrument(Win32PrintService.class.getName(), pool);

  JarOutputStream jar = new JarOutputStream(new FileOutputStream("target/PrintServiceFixer.jar"));
  addClass(jar, Win32PrintService.class.getName(), "java");
  jar.close();
 }

 private static void addClass(JarOutputStream jar, String clazz, String target) throws IOException
 {
  byte[] buf = new byte[8192];
  int read;

  String name = clazz.replace('.', '/');

  JarEntry jarEntry = new JarEntry(name + ".class");
  jar.putNextEntry(jarEntry);

  InputStream is = new FileInputStream("target/" + target + "/" + name + ".class");
  do
  {
   read = is.read(buf);
   if (read > 0)
   {
    jar.write(buf, 0, read);
   }
  }
  while (read > -1);
  is.close();
 }

 private static void instrument(String clazz, ClassPool pool) throws NotFoundException, CannotCompileException, IOException
 {
  CtClass ctClass = pool.get(clazz);
  for (CtMethod cMethod : ctClass.getDeclaredMethods())
  {
   if (cMethod.getName().equals("getPrinterIsAcceptingJobs"))
   {
    System.err.println("replacing getPrinterIsAcceptingJobs");
    cMethod.setBody("return javax.print.attribute.standard.PrinterIsAcceptingJobs.ACCEPTING_JOBS;");
   }
  }
  ctClass.writeFile("target/java");
 }
}

This helper looks up the Win32PrintService class and instrument the bytecode in a what that the check for "PrinterIsAcceptingJobs" always returns: Yes, the printer is accepting jobs.
Finally, it bundles the resulting class in a jar file named PrintServiceFixer.jar - created in a directory named "target".

You should see

replacing getPrinterIsAcceptingJobs
on the console output. If this line is missing, your JDK/JRE version needs another trick.

Now you have to start your program with the "bootclasspath" option like this:

-Xbootclasspath/p:target/PrintServiceFixer.jar

Java will load our patched version of Win32PrintService instead of the original one - and - tata - your program no longer suffers from

javax.print.PrintException: Printer is not accepting job
exceptions.

Best will be you create a jar file per JRE/JDK version you use and carefully use the right version, else you might encounter more problems than you are going to fix.

If you would like to fix the PrintService for your platform, try to find the Class name of the platform dependent PrintService implementation and see if there is a method like "getPrinterIsAcceptingJobs". Change the helper class above accordingly and run it.

Another option to fix that problem is to use AspectJ with runtime weaving, but I often found myself to be too impatient with the resulting slower startup times of the application.
Anyway, you know what you should looking for now and it should be easy enough to create a pointcut.

Happy printing!

Donnerstag, 5. März 2009

Avaje - Repeatable Read and Auto-Fetch

code hosted at copy-con-goodies

Today I'll tell you something about Avaje, my new best friend for database access.

First of all, one can not say that this library is bug-free, but Rob (as far as I know the main developer) makes a very good job in applying my patches ;-).
Seriously, it is an awesome piece of code which is just to young to work in each and every use-case JPA is designed for. What makes it my fav is, that I managed to dig into the code in just one weekend. Nicely structured!

Repeatable Reads

The first thing you have to take into account - compared to any other JPA implementation - is, that Avaje does not need a PersistenceContext, for an Web-Application this means, you do not have to make sure you issue each database request against the same PersistenceContext.
If you look at this example you can find the following lines of code:
    // read entity without transaction ... this automatically creates one just for this very statement
    TestEntity readEntity1 =
        server.find(TestEntity.class, 1L);

    // and again. We now read the same database row but got two independent instances
    TestEntity readEntity2 =
        server.find(TestEntity.class, 1L);
Withouth any provisioning you will get two instances of the same row. Sure, you have to keep in mind that, if you change and update readEntity1 and later on you do the same with readEntity2 you will face a concurrent modification and get an exception. But how often will you have to deal with that on a web-page?

Now, if you need the feature to get the same instance for the same entity you simply put a transaction around, so the code above becomes:
    // now lets start a transaction
    Transaction tx = server.beginTransaction();
    TestEntity readEntity1_1 =
        server.find(TestEntity.class, 1L);

    TestEntity readEntity2_1 =
        server.find(TestEntity.class, 1L);

    // we now got the same instance for the same row  
    tx.commit();
This effectively means you can have the best of both worlds. Normally you would not care about "repeatable reads" and simply use your entities, if (for example you start multiple processes to update various data) you need to ensure to get the same instance from an database access you simply put a transaction around.
And this is something you would do anyway as you will update data, no?

Auto-Fetch

Another VERY nice concept of Avaje is auto-fetch.
I've added a little code to the exaple code above which allows you to dig into that feature.
I will see I access the property field1 and field2 from the various bean instances.
  readEntity1.getField1(); // read content of field1

  readEntity2.getField2(); // read content of field2
On the first run the sql for reading readEntity1 you will see Avaje will fetch (not very surprisingly) all the properties from the database
<sql summary='[TestEntity]'>
    select e.ID c0, e.FIELD_1 c1, e.FIELD_2 c2, e.VERSION c3 
    from TEST_ENTITY e
    where e.ID = ?  
</sql>
But at the end Avaje will collect the statistics and persist them into a local file using the .autofetch extensions.
Now, on the second run the sql will look different
<sql summary='[TestEntity] autoFetchTuned[true]'>
    select e.ID c0, e.FIELD_1 c1, e.VERSION c2 
    from TEST_ENTITY e
    where e.ID = ?  
</sql>
Do you notice? FIELD_2 is no longer fetched from the database.
It might happen that you change your code, or your programm takes other routes through the code and it requires FIELD_2 now, Avaje will fetch the field lazily and learn this fact. Next time it will prefetch it too.

This also works for e.g. OneToMany associations. This means, you no longer have to think about making an association lazy or not, it also frees you from making associations lazy - and then adding code to load them eager sometimes.
Avaje simply will learn that from your code by capturing the stack-trace and storing access information to these points.

Imagine what a performance boost this can be for your program!

You can find more infomation about this astounding feature here.

Dienstag, 3. März 2009

Apache MyFaces Orchestra

Lately jsfcentral released a podcast which Kito recorded with Simon Kitching and me at JSFDays 2008.

This podcast is about Apache MyFaces Orchestra at its youngest days.

In the meantime a lot of things happend. One thing is, that I started to write a real Rich-Client application using Swing.
I had to reconsider everything ... My well known (so called) web-application-stack was no longer usable. No JSF, no Tomcat, no Servlets.
During this process I also thought about the database access layer. JPA is a great thing (I think), but some stuff around it is ... a hell.

As JPA implementation I use Hibernate which is also a great thing, but in the end, JPA does not necessarily make things easier.
The problem I have with ORM/JPA is the full transparency. It is funny, exactly this concept should makes things easier. But for me, it made things more complicated. It even forced me to build Apache MyFaces Orchestra to have a decent conversation scope.
Sure, I could have used JBoss Seam or Spring Web-Flow. But Web-Flow is to far away from standard JSF (for my opinion) and JBoss Seam ... I simply did not get how it worked.
However, with Orchestra there is simply a third choice, and all three choices are working very well ... if ... yes, if you would like work transparently with your entities (database objects).

  1. Transparently means, you change a property and somewhere at the end of the conversation a commit() finally persist it.
  2. Another thing which ORM solves are repeated reads of an entity with the same primary key. The ORM implementation will simply fetch it from the in-memory cache and you will always see the same instance.
    This is fine as if you changed the entity somewhere else you can be sure to see this change without having it persisted to the database.

Other stuff like lazy loading of associations or the database-independent creation of SQL statements can be expected from any other database access layer too, not neccessarily being 100% transparent, though.

Ok, (1) and (2) are really nice to have, but is it that a deficit not to have that?
I never managed to have that a perfect object hierarchy so that I did not have to call at least PersistenceContext.save(entity). Creating such a perfect object hierarchy is not easy and I doubt that it will lead to an overall performant database access.
And for (2): When are those repeated reads really necessary to being handled at "database session" level?
Even with Orchestra you can simply cache the entity yourself in the conversation-scoped backing bean of your JSF page. The only requirement which pops into my mind are "processes". Think about processes as various business modules of your appliation you compose together to a business-process.
But this composition will run normally within the same "transaction", so it is sufficient to have this "repeatable read" stuff working just for the "time of a transaction".
Hmmm ... I should write about that separately.

Once you buy that, you will find yourself writing easier maintainable programs. You just have full control over what happens when and why again.

To sum up:
  • Do not mind to call something like .save(), .delete()
  • Cache your entity as long as required and do not rely on "repeatable read"

The good thing is, that Orchestra is still usable in this scenario as the conversation scope is usable anyway - it defnitely will make your web-application development easier - but it is no longer required to have the persistence context being synchronized with the lifetime of the conversation. You simply use Orchestra without any PersistenceContextInterceptor.

The downside here is the requirements of JPA which will not play nicely here due to the "session" data it maintains to make all the transparency work.

Thanks to Simon Kitching who pointed me to Avaje I became aware of a library which works much like a JPA database access layer, but keeps a database session just for the transaction time. EXACTLY what I searched for.
Being able to stick with well known annotations, but without all the hassle you have with the 100% transparency "forced" by JPA.

My code did not change that much. But no session cache bloats my memory, no unused entities are hanging around in memory which you have to get rid somehow, no nested conversations if you e.g. navigate to a search page and back again.
It is hard to express, and a Blog is all about writing about personal feelings, but if you too think that JPA - as it is now - can't be the end, have a look at Avaje.
My next blog will be about Avaje ... stay tuned.

Montag, 2. März 2009

What is "copy con"?

Well, I am getting old, and so I undergo a lot of hassle with computers.

One of those was when something (no, it was not me ;-) ) crashed your ms-dos config.sys file (for those who remember) which you had no backup of ... as usual.

Once, due to the absence of any working editor, I had to use "copy con" to recreate this file.

So
copy con: config.sys
allowed me to copy the CONsole input to a new config.sys.

Care had to be taken taken to enter everthing correct the first time, else you had to start over as there was no way to edit previously entered lines.

Thas was fun!

BTW: This still works even with Windows 2008, for sure, no config.sys, but try
copy con: blog.txt
- and enter some text. (To stop editing you have to press "Ctrl-Z" and Enter)

Sonntag, 1. März 2009

Just a test after adding syntax highlighter to the blogger layout template.
function bold()
{
    if (a < 0)
    {
        System.err.println("no ....");
    }
}
Btw, here is a "how to do that"