Sonntag, 8. November 2009

Hack Java 6 to let SOAP headers for web services be set

Java 6 (and NetBeans) make it extremely hard to let people set SOAP headers.

( UPDATE AT END )

How to normally do it is outlined in the metro guide:
https://metro.dev.java.net/guide/SOAP_headers.html

and looks like this:
WSBindingProvider bp = (WSBindingProvider)port;
bp.setOutboundHeader( Headers.create(new QName("simpleHeader"),"stringValue") );

( Hm, in Java 6 there is only bp.setOutboundHeaders with an "s" at the end... )
Problem is the WSBindingProvider is in an internal package in Java 6.
So javac or NetBeans won't let you compile the code.
( Eclipse lets you btw. if you allow internal class usage in the preferences. )

So what can we do ?

1. Maybe this: http://devplace.wordpress.com/2007/09/24/adding-soap-header-in-java/
in combination with:

BindingProvider bp = (BindingProvider) port;
bp.getBinding():
...

2. Fight the authority and use reflection once again:

public static void setHeader(MyPortType port, String session) throws Exception {
Method[] methods = port.getClass().getMethods();
for (Method method : methods) {
if (method.getName().equals("setOutboundHeaders")) {
Class<?>[] parameterTypes = method.getParameterTypes();
for (Class<?> class1 : parameterTypes) {
if (class1.getName().endsWith(".List")) {
Object h = getHeader(session);
List l = new ArrayList();
l.add(h);
method.invoke(port, l);
return;
}
}
}
}
}


public static Object getHeader(String session) throws Exception {
Class<?> header = Class.forName("com.sun.xml.internal.ws.api.message.Headers");
Method[] methods = header.getDeclaredMethods();
for (Method method : methods) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 2 && parameterTypes[0].getName().endsWith("QName")) {
return method.invoke(null, new QName("http://schemas.domain.com/2005/01/Product/types", "session"),
session);
}
}
return null;
}
The method getHeader acquires an instance of forbidden Headers class and invokes
the static method "create" to return a new Header object.
(In my code it is only called from the other method "setHeader".)

The method setHeader searches for a method called "setOutboundHeaders"
in the port object which accepts a List object as its parameter.
Then it acquires a new Header object, stuffes it in an ArrayList
and invokes the setOutboundHeaders method.
Voilà.

( Yeah I know I could make better use of the parameter method search, but hey... )

UPDATE:
Here are the refined, clean, loopless methods:


public static Object getHeader(String session) throws Exception {
Class header = Class.forName("com.sun.xml.internal.ws.api.message.Headers");
Method method = header.getDeclaredMethod( "create", QName.class, String.class);
return method.invoke(null, new QName("http://schemas.domain.com/2005/01/product/types", "session"), session);
}

public static void setHeader(MyPortType port, String session) throws Exception {
port.getClass().getMethod("setOutboundHeaders", List.class).invoke(port, Arrays.asList(getHeader(session)));
}


public static void setURL(MyPortType port, String url) {
BindingProvider bp = (BindingProvider) port;
Map rc = bp.getRequestContext();
rc.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
}

Samstag, 10. Oktober 2009

Set Apache Element Construction Set to pretty print

Unfortunately there is no easy way to overwrite the default settings
for the Element Construction Set to make it print pretty HTML.

After playing around with the only official way which is to set a comandline option:
For example, java -Decs.properties="my.ecs.properties"
and trying
System.setProperty("ecs.properties", "ecs.properties");

I fell back to using reflection.

This little piece of code does the trick:


try {
Field fld = ECSDefaults.class.getDeclaredField("defaults");
fld.setAccessible(true);
ECSDefaults ed = (ECSDefaults) fld.get(null);
Field pp = ECSDefaults.class.getDeclaredField("pretty_print");
pp.setAccessible(true);
pp.setBoolean(ed, Boolean.TRUE);

} catch (Exception ex) {
Logger.getLogger(Report.class.getName()).log(Level.SEVERE, null, ex);
}

IMPORTANT: Add this BEFORE you construct your document,
i.e.: Html h = new Html();
otherwise it doesn't work.

Sonntag, 24. Mai 2009

Jboss Tools & Seam

I wanted to work with JSF ever since I had used Sun's Java Studio Creator back when it was in early access.

WOW, I thought to myself, finally a WYSIWYG IDE for web applications.
I was blown away...

But soon, working on a test project, the IDE bugs haunted me, not even going away with the final and updated version of the creator...

When it was merged into NetBeans I tried it again, but something didn't feel right... Sun's enhanced JSF library ( Woodstock ) was very propriatory and the future seemed to be JSF and JPA.
But the JSF/JPA project from NetBeans was without visual help...

Also, pure JSF/JPA has a very tricky way to get paging working with very large datasets which was not drag&dropable in NetBeans. ( JSF DataModel )

Hmm, I was unhappy, what was left of Sun's Java Studio Creator's promise ?

Searching the web for JSF libraries I found ICEFaces.
They didn't solve the paging problem, but had very powerful AJAX features on top of JSF.
Later I even found a promising paging demo in the then unreleased 1.8 examples... I was getting hopeful again.

I played around with ICEFaces using the Eclipse plugins for two days just to understand the basics... quite a steap learning curve.
( Keep in mind I never wrote JSF by hand before, as Creator did all of that for me... )

Hmm that wasn't perfect either, why do I need managed beans if I have an entity bean with all the same values ?

That was when I found Seam and its way of getting rid of much config XML and those stupid managed beans. I had heard about it before so I decided to give it a try.

Cool, there are even eclipse plugins for it, the JBoss Tools !

But WOW, they are overwhelming... so many new options, so many new resources.

I needed to take a step back, so I looked for a Seam book and found the so far, very good to read Seam in Action from Manning ( http://mojavelinux.com/seaminaction )

But the book used the seam-gen command line tools... not what I wanted.
But hey, I gave it a try and it worked, but still, I wanted to work in a IDE and have tool support. ( Yes, I know I can import a seam-gen project... )

So I went back to the IDE and startd to play around. At least now I had a better understanding of the terminology. So the book helped me alot to get myself comfortable with the tools. ( BTW: http://www.jboss.org/tools )

The online documentation for the tools don't help at all with what to do after a project is generated... How to turn in it into your project.

So more playing around was necesary, and boy was it painful.
Let me give you some of the most important things I learnd so far:


1. Use old stuff !

Use the last version of: Jboss application server ( 4.2.3 not 5.X), Seam ( 2.0.X maybe 2.1 ), Java (1.5 not 1.6)

If not you will be in for a lot of pain!
So much stuff goes wrong if you want to make a WAR project if you switch out one of these things with a current version.
( EAR works better, but overwhelmes again. )

You can use the current Jboss Tools, that's ok.


2. Don't use a DB in embedded mode.

DON'T use a java DB like HyperSonic SQL in embedded mode !
The tools and JBoss App Server NEED concurrent access and you will get so much frustrating trouble if you do...

I used HSQLDB embedded first because it was easy... don't !
Read the docs how to run it in stand alone server mode and do it.


3. Customizing the reverse engineering process

You will never guess how to customize the Java classes and attribute names if you generate your entities from an existing DB with JBoss Tools:

In the Seam perspective there is a little new run button with a hibernate symbol. There is a sub option called: "Hibernate Code Generation Configurations..."
There you will find a configuration for your project if you executed "Seam Generate Entities" in the "New" Wizard.
Its this magic place where you can browse to a reveng.xml file which you create easily prior with the hibernate tools ( part of JBoss Tools ).
And then rerun and voilà new entities and xhtml files

( Now you just need to get rid of the old ones :-(
Also, this did not work with MySQL for some reason, but with HSQLDB )

Please JBoss guys, add a page in the Seam wizards for a reveng.xml file !!!


4. Schema Validation

If you generate a project from existing tables, the tools will set the hibernate.hbm2ddl.auto property to validate... boy will you get errors!
You will scramble, you will search, you will change java code and table column types. The easy fix ? Remove the word validate leaving emtpy "" quotes...


5. Restrictions ( This is the best ! )

Great now you have a nice little web application, much like phpMyAdmin.
Everyone can see everything... logged in users additionally can change everything.
But thats not what you want, many times you want users to see their own stuff only !

How can you do that with classes extending EntityQuery which provide the tabular data ?
Should you do something to that getEjbql() function maybe ?
No, add restrictions !

In the generated class you will see a RESTRICTIONS constant.
The trick is to know that you can add any restriction to that array and Seam will use and add that restriction if and only if the expression language (EL) variable in the string has data.
So in my authenticate method I simply set a variable in a new session scoped component which I use in my restriction.

WOW, I found this 3 days trying to find a solution for this.
( Yeah, I bet the book explains it later too... but I'm only in chap 3 )

I may write a little tutorial on how to make a Seam WEB project your own.
Stay tuned.

Montag, 4. August 2008

major issues with the latest Ganymede update and SVN

Be aware that there are major issues with the latest Eclipse update ( Mylyn related )
and if you have used subversive from the Ganymede update site. ( Like I recomended ).

You will have many error windows when u open a SVN project.

The solution is to update subversive by using the "official"
update site;

http://download.eclipse.org/technology/subversive/0.7/update-site/

You can add it, or if its already there use "manage sites..."
to show it.

There select the newer "SVN Team provider".

Then maybe the connectors again from

http://www.polarion.org/projects/subversive/download/eclipse/2.0/update-site/


( I don't know as I reinstalled... due to the issues )

Mittwoch, 16. Juli 2008

Search for Java casts

Here is a little regular expression which
allows you to search for Java casts.

Its not perfect, but a good starting point.

\([a-zA-Z]+\)

Montag, 7. Juli 2008

Eclipse 3.4 Ganymede and subversion repositories

I tried out the new Eclipse version 3.4.

I really has some nice new features.
But it also was very hard to get it to behave
properly with subversion repositories.

Here are my findings:

1. Don't use subclipse anymore.
The current version does not work properly with Eclipse 3.4

2. It seems that subversive has won the "battle" for default eclipse svn plugin.
( http://www.eclipse.org/subversive )

3. It is now even "included" with 3.4. But you have to select it for installation.

3.5. download and install Eclipse Ganymede
( Eclipse IDE for Java EE Developers (163 MB) )

4. install subversive BEFORE you import any project.
Or you get in trouble.

"Help" -> "Software Updates..." -> "Available Software" -> "Ganymede" ->
"Collaboration Tools" -> "SVN *"

( Please note, that I have installed 3.4 in a new directory with a new workspace,
I do not recommend any other way of installation, due to my SVN plugin switch. )

5. In the Software Updater add a new Site;
http://www.polarion.org/projects/subversive/download/eclipse/2.0/update-site/

Install the JAVA HL 1.5 svn connector from that site.

5.5. Restart eclipse.

6. Choose "File" -> "Import..." -> Existing projects into workspace.

If everything is correct, you should see your projects and
also in [brackets] the path to the svn server.

7. If you have troubles check the classes directory,
There may NOT be any .svn directories there.
Subversive WILL NOT work correctly if so.

If you have these, close all projects and
manually delete all files in the classes directory.
Then open your projects again.

3 cool Eclipse 3.4 tricks

1. If you have a piece of code in the clipboard,
select a package on the left inside the package explorer.
Then press ctrl+v to automatically create a new Snippet.java
with a class and a main method. Inside ? Your code from the
clipboard, ready to test.

2. If you have a line with a function call like System.getProperties();
Press Ctrl+2, release and then press L.
This create a new variable of the proper type and even
a reasonable name. Its one of the greates time savers !

3. Ever wondered why sometimes the function parameter help
in Eclipse shows the parameters you are currently supposed to enter
and sometimes not ? Well after you type in an object name, type "."
to get the list of functions, then select one and press enter.
Now you get the parameter hints. If you moved the cursor around
and lost the hint, just go behind the inserted function name and
press ctrl+space and then select the function and then press enter.
Basically pressing enter after the selection is the trick.