This doesn't really say much. However, after some googling, I can explain some of the attributes, and what is actually useful to use.
If you want to show both date and time: dd-MM-yyyy hh:mm:ss you can use type="both" and dateStyle="full". If you want to show only date. Use type="date".

You choose from a range of different dateStyle.default May 14, 2007 2:35:45 PM ( Default Value)
short 5/14/07 12:55:42 PM
medium May 14, 2007 2:42:36 PM
long May 14, 2007 2:41:08 PM
full Monday, May 14, 2007 2:39:56 PM

However what I have found the most useful is just to use the pattern attribute together with the type.
So if you want the style 14.07.2009 you just write

Monday, November 23, 2009

Just wanted to give a quick GOTCHA I discovered with Axis 2. The other day I wanted to install and use lombok (which is AWESOME by the way).

However lombok needs Java 6 to run, and my WebService was compiled with Java 5, so I changed to Java 6, recompiled, but obviously forgot to recompile the WebService client stubs.
I didn't get any exception that remotely told me that I had a class version issue. However, I got this exception:

com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog

After reverting back to Java 5, everything worked just fine. So just a heads up.

Friday, November 20, 2009

So I just returned from the Seam / Infinispan meetup here in Devoxx and there where a few GOTCHA that I will come back to.

Firstly, the meeting it self was pretty awesome. Although I feel that the Seam discussion wasn't that coordinated as the Infinispan talk. There were too much focus on Weld, but I guess thats not surprising since Weld was just recently released, and most Seam developers except poor Norman Richards, where working on Weld to get it finished before the deadline.Don't take my words literally, Norman might have done some work towards Weld for all I know, but he was at least the only one working on Seam 2.

Anyways, the ones from the Seam team who where present (forgive me if I forget someone) where: Pete Muir, Dan Allen, Norman Richards, Shane Bryzak and Christian Bauer.Dan held a quick intro on Seam, for the 3 people who didn't know what Seam was, and then Pete talked a bunch about Weld, and finally Dan closed with showing a very cool testing framework which I cannot remember the name of now which will be implemented for Seam 3, and also Rest on Seam. Of course with a lot of Q&A in between.

So finally I got a chance to speak with Dan, Norman and Pete. I really wanted to have a chat with Shane as well, but unfortunaltly by the time I went to get a beer and come back he was gone. :-(First I got a chance to ask Dan about the strange behaviour I found regarding injection of a stateless EJB in Seam, discussed here , and he confirmed what I suspected all along, that it was infact a bug in Seam. Now, I he didn't actually say "That is a bug" per say, but he did say "If that doesn't work, it is a bug in Seam". But from my experience I can safely conclude that this is a bug in Seam.Before you say "Hey, why don't you file a JIRA on it", I will tell you why I will not.After talking with Pete, I discovered that infact there WILL BE NO MORE releases of Seam. Meaning, even if there are any bugs, or even if someone in the community upload a patch, or even some core devel0per fix the bug in the Seam 2.2 branch, there will be no official release of it. You can however checkout a version of that fix and build binaries for your self.I know, pretty lame and to be honest a big surprise from my part. But Pete did explain why, and the reason is that before shipping an official release, it has to go to the QA team for testing, and probably some other branches and this takes up rescources that JBoss doesn't want to commit to. Instead they want to focus on the development and shipping Seam 3, which is planned to come around march 2010.So you must ask your self "What about us who are using Seam 2.x and really need to fix this and that issue? Is all hope gone, other than fixing it our selves and running a build?" The answer is no. If you REALLY want something, basically all you have to do, is buy a support deal from JBoss or a certified JBoss partner (as we are), and ask them to fix it. JBoss will then put resources into fixing that and actually commiting the fix in the branch so that it is available for everyone to checkout and build, however, they still will not release a version of that fix. You have to build it your self.

Lastly, this blog post deserves to be mentioning what Seam 3 will look like. Though this is not official or final, it is what I know has been discussed and agreed upon.Seam 3 will be what is missing from the Java EE 6 stack. Everything thats sort of extra that didn't get into the spec. It will obviously contain all the pdf, rss, excel goodies we are familiar to from Seam 2, including JBPM 4 and Drools 5 support. Not to forget all the goodies that comes with Java EE 6, Bean validation, Servlet 3.0, EJB 3.1, JPA 2 and so on. It will also be modular based, meaning, that if you only need certain parts of Seam, then it is no need to get anything else which is irrelevant to you. There is probably more that I have forgotten, but Pete will blog about this pretty soon.Lastly, I want to mention that I did try to encourage the people to participate on the seam forums, and help people that are struggling with their Seam 2.x apps. Because face it; those people are most likely to move to Seam 3 and Weld, and if you want them to do that, you should try to make the learning curve of Seam 2.x as little as possible.Pete did agree, however he did say that the reason why he couldn't reallly encourage the core developers to use more time on the forums is because of all the time they spent on getting Weld finished. 14 hour(!) days jikes. But hopefully in the future, they will have more time to help the users out there.

Thursday, October 8, 2009

There seem to be a problem with IE8 and Seam applications. We are running Seam 2.1, JSF 1.2 and Facelets, and I cannot say for sure where the bug is. For all I know its a bug with IE8.

There seem to be problems when creating long-running conversations. In link using IE8 the cid doesnt appear. Somehow it is stripped or doesn't render correctly, and it causes some strange behaviour.When trying to create a long running conversation by pushing an edit link for instance, we get a "Your session has timeout" exception.

We fixed this IE8 problem by telling Internet Explorer to emulate IE7 in pages.xml

It seems like ant will just put all the libraries in the lib folder in the classpath, and eclipse obviously would not. Thus, when the wicket jars where removed, the tests where back online. I believe it is sufficient to remove jboss-seam-wicket.jar and jboss-seam-wicket-ant.jar, however I just removed all jars that included the name wicket.

Wednesday, June 17, 2009

So I have read the Seam 2.x Web DevelopmentBuild Robust Web Applications with Seam, Facelets, and RichFaces, using the JBoss Application Server

This book tries to cover a very very large aspect of Seam and friends.The book has 11 chapters and almost 300 pages. If you are new Seam, this is a great kick start. Because the book covers a huge portion of the most important aspects of Seam, plus some advanced topics such as Remoting, however I feel that the chapters are too small and that they don't give a thourough and in depth explanation. Many of the examples can be found by googling a bit and reading the documentation of Seam, but this is why it is so good to have a book covering a very large portion of it.

The RichFaces chapter could have been improved alot. Around 30 pages is hardly enough to cover this very big framework. I believe you will get more out of downloading the live examples and looking at the source code and playing around with it instead.

So to sum up, this book is good for someone new to Seam, that want an overview of most of what Seam has to offer, however I would supplement with Seam in Action to cover more ground.

Monday, April 6, 2009

Here is all the unique annoations we are using in our project (Seam 2.1.1, Hibernate, JPA, EJB 3 annotations) with a short explanation on each of them.

@AroundInvoke -- To add an interceptor to a bean, you need to write a class with a method annotated @AroundInvoke and annotate the bean with an @Interceptors annotation that specifies the name of the interceptor class.@Asynchronous -- Specifies that the method call is processed asynchronously.@AutoCreate -- Specifies that a component will be automatically created, even if the client does not specify create=true. @Basic(LAZY) -- Tells the entitymanager to lazily fetch the column. This is not needed since that is the default.@Begin(flushMode = FlushModeType.MANUAL) -- Begins a long running conversation and sets flushmode to manual. Doesnt execute operation until flush() is called.@Begin(join = true) -- Specifies that if a long-running conversation is already in progress, the conversation context is simply propagated.@BypassInterceptors -- disable interceptors for the component. Features such as bijection, annotated security restrictions, synchronization and others are unavailable for components marked as @ByPassInterceptors.@CaptchaResponse(message="#{messages['verificationError']}") -- Tells what kind of message the response of the captcha should be@CollectionOfElements --hibernate annotation that is used in conjunction with Embeddables.@Column(length=16777215, nullable=false) -- sets an entity column to 16kb in length and not null@Column(unique = true) -- Sets this column to be unique@Create -- Specifies that the method should be called when an instance of the component is instantiated by Seam. Note that create methods are only supported for JavaBeans and stateful session beans.@DataModel -- Exposes an attribute of type java.util.List to the JSF page as an instance of javax.faces.model.DataModel. This allows us to use the list in a JSF <h:dataTable> with clickable links for each row.@DataModelSelection -- Annotation that tells Seam to inject the List element that corresponded to the clicked button@Deprecated -- Marks the method or class as deprecated@Documented -- Used in conjuction with creating annotations. Will make the annotation available in JavaDoc@Duration -- Specifies that a parameter of the asynchronous call is the duration before the call is processed (or first processed for recurring calls).@Email -- Hibernate validator for emails@Embeddable -- Marks a class as Embeddable @Embedded -- Classes that are Embeddable will be Embedded in the other class that uses them. IE, Address is embeddable, and is @Embedded in Person @End -- Specifies that a long-running conversation ends when this method returns a non-null outcome without exception.@Entity -- Marks a class as an Entity@Expiration -- Specifies that a parameter of the asynchronous call is the datetime at which the call is processed (or first processed for recurring calls).@Factory(value="officerAdminContact", scope=ScopeType.EVENT) -- Creates a factory with the name officerAdminContact with a scope of Event.@Filter(name="orgFilter",condition = "organization_id = :orgid") -- Marks a class as hibernate filter with the name orgFilter, and sets the condition of the filter@FilterDef(name="orgFilter", parameters = { @ParamDef(type="long", name="orgid")}) -- Hibernate annotation that defines a filter. The name defines which filter should be defined, and sets what kind of parameters the filter has.@GeneratedValue -- Sets a id to be generated automatically@Id -- Sets an attribute as Id for the entity@In(create = true) -- Injects the field and if it is null, it will create the field@In(required = false) -- Injects the field and tells seam that this field can be null, and will not be created if it is null@In(required=false, scope=ScopeType.APPLICATION) -- Injects a field and sets the scope to be Application wide@In(scope = ScopeType.BUSINESS_PROCESS) -- Injects a field and sets the scope to be BUSINESS_PROCESS@In(value = "#{s:hasRole('sysadmin')}") -- Injects a field with an EL expression that returns true or false. In this example true if the user has role of sysadmin. @In(value = "org.jboss.seam.bpm.jbpm") -- Injects a seam component that bootstraps a JBPM SessionFactory@Inherited -- Indicates that an annotation type is automatically inherited. Used in conjunction with creating annotations.(?)@Install(precedence = Install.APPLICATION) -- The @Install annotation lets you control conditional installation of components that are required in some deployment scenarios and not in others. This is useful if: *You want to mock out some infrastructural component in tests. *You want change the implementation of a component in certain deployment scenarios. *You want to install some components only if their dependencies are available (useful for framework authors). APPLICATION is the default precedence. This is appropriate for most application components.@JoinTable(name = "ProcessUserRoles", joinColumns = @JoinColumn(name = "userId"), inverseJoinColumns = @JoinColumn(name = "roleId")) - Tells which table and what column should be joined in a table.@Lob -- Persistence annotation that specifies that the attribute should be a large object.@Local(ArchivingConnector.class) -- Tells the ejb which interface is the Local. An EJB can use local client view only if it is really guaranteed that other enterprise beans or clients will only address the bean within a single JVM. If this is the case, such access will be carried out with direct method calls, instead of RMI.@Logger -- Seam's Log4J.@ManyToOne(fetch = FetchType.LAZY, optional = true) -- Defines which filed is ManyToOne relation, with default fetch size as LAZY and that the field is optional (can be null)@Name("lostPasswordAction") -- Creates a seam component with the name "lostPasswordAction"@NamedQuery(name = "applicationprocess.find", query = "select ap from ApplicationProcess ap join ap.organization o where ap.name = :processName and o.name = :orgName") -- Creates a named query with the name "applicationprocess.find" which will execute the specified query. This means that you can call the query like this: entityManager.createNamedQuery("applicationprocess.find").getResultList();@Namespace(value="http://kommuneforlaget.no/products/saksapp/process") -- Specifies the configuration namespace of a Java package containing Seam components.@NotEmpty -- NotEmpty checks for not null and empty@Observer("org.jboss.seam.security.loginSuccessful") -- An observer listens to the following event. In this example it will listen to successfully logins@Officer -- Custom annotation that defines a class or a method as restricted with the role of Officer@OneToOne(cascade = CascadeType.ALL) -- One to one relation with all cascading@Orgadmin -- Custom annotation that defines a class or a method as restricted with the role of Orgadmin@Out(required = false) -- Outjects the variable in the seam scope event and tell that the object can be null. Similar as request.setAttribute("bestRestaurant", restaurant);@Out(scope = ScopeType.EVENT, required = false) -- Same as above, because the default scope in Seam is EVENT.@Out(scope=ScopeType.SESSION, required=false) -- Same as above only the scope is set to SESSION@Override -- Marks a method as Override. This tells the compiler that this method should override a parent method inherited.@Parent -- A hibernate annotation that reference the property as a pointer back to the owner (generally the owning entity)@Pattern(regex="\\D*-\\D+") -- Hibernate validator that checks the value with a regex pattern@PermissionCheck("upgrade") -- Override the default permission action name (which is the lower case version of the annotation name) with another value. Used in conjuction with custom annotations.@PostConstruct -- javax.annotation.PostConstruct. Used on a method that needs to be executed after dependency injection is done to perform any initialization. Only one method can be annotated with this annotation. The method MUST NOT have any parameters except in the case of EJB interceptors in which case it takes an InvocationC ontext object as defined by the EJB specification. The return type of the method MUST be void. The method MUST NOT throw a checked exception. The method on which PostConstruct is applied MAY be public, protected, package private or private. The method MUST NOT be static except for the application client. If the method throws an unchecked exception the class MUST NOT be put into service except in the case of EJBs where the EJB can handle exceptions and even recover from them. @PrePersist -- JPA annotation that will be called right before a persist is done. Similar annotations are: PostPersist, PreUpdate, PostUpdate, PreRemove, PostRemove and PostLoad.@RaiseEvent("templateHandler.pdf") - If a method is annotated with @RaiseEvent, it will raise an event with the name "templateHandler.pdf" after the method is finished. @RequestParameter -- Specifies that a component attribute is to be injected with the value of a request parameter. Basic type conversions are performed automatically.@Restrict("#{s:hasRole('orgadmin') or s:hasRole('sysadmin')}") -- Tells seam that the class can only be used if the role is orgadmin or sysadmin@Retention(RUNTIME) -- Indicates how long annotations with the annotated type are to be retained. If no Retention annotation is present on an annotation type declaration, the retention policy defaults to RetentionPolicy.CLASS.@Role(name="asyncReminderAction", scope=ScopeType.EVENT) -- Allows a Seam component to be bound to multiple contexts variables. The @Name/@Scope annotations define a "default role". Each @Role annotation defines an additional role. * Name — the context variable name. * scope — the context variable scope. When no scope is explicitly specified, the default depends upon the component type.@RoleCheck -- Meta-annotation that designates an annotation as being a role, requiring a security check prior to invoking the annotated method or class.@RoleName -- Flags an entity field or method as representing the name of a role@Scope(ScopeType.CONVERSATION) -- Sets the scope to be CONVERSATION@Scope(ScopeType.EVENT) -- Sets the scope to be EVENT (default)@Scope(ScopeType.SESSION) -- Sets the scope to be SESSION@Startup -- Specifies that an instance of this component is created at system initialization time for an application scoped component, or when a session is started for a session scoped component. May only be applied to APPLICATION or SESSION scoped components.@Stateless -- Component-defining annotation for a stateless session bean. @SuppressWarnings("unchecked") -- Tells the compiler to suppress warnings of type unchecked. Normally from entityManager.createQuery().getResultList()@Sysadmin -- Custom annotation that defines a class or a method as restricted with the role of Sysadmin@Target({TYPE, METHOD}) -- Indicates the kinds of program element to which an annotation type is applicable.@Temporal(TemporalType.TIMESTAMP) --JPA annotation for date attributes. This will set the timestamp on a variable automatically@Test(dependsOnMethods = "setup") -- TestNG annotation that defines this test to be dependant on a test called setup, and cant be run until that test is finished.@Transactional -- Specifies that a JavaBean component should have a similar transactional behavior to the default behavior of a session bean component. ie. method invocations should take place in a transaction, and if no transaction exists when the method is called, a transaction will be started just for that method.@Transient -- Defines this field to be transient. It will not be stored or serialized.@UniqueConstraint(columnNames = "{name,organization}") -- JPA annotation that in this case defines that the attributes name and organization together should be unique.@UserFirstName -- Flags an entity field or method as representing the first name of a user@UserLastName -- Flags an entity field or method as representing the last name of a user@UserPassword(hash = "md5") --Flags an entity field or method as representing the password for a user. The hash method that is used is md5 here. However sha is more secure, and "none" is also a valid option, which will not hash anything.@UserPrincipal --Flags an entity field or method as representing the principal (username) for a user@UserRoles --Flags an entity field or method as representing the list of role memberships for a user@Valid -- Hibernate validator that enables recursive validation of an associated object. If used on an field, it will check all the fields validators, ie @Valid Address address = new Address(); will check all the validators of class Adress.@Validator --Allows a Seam component to act as a JSF validator. The annotated class must be a Seam component, and must implement javax.faces.validator.Validator.@Version --JPA annotation that specifies the version field or property of an entity class that serves as its optimistic lock value. The version is used to ensure integrity when performing the merge operation and for optimistic concurrency control. Only a single Version property or field should be used per class; applications that use more than one Version property or field will not be portable. The Version property should be mapped to the primary table for the entity class; applications that map the Version property to a table other than the primary table will not be portable. @WebParam(name="data") --Used with WebServices and is used to customize the mapping of a single parameter to a message part or element.@WebService -- The purpose of this annotation is to mark an endpoint implementation as implementing a web service or to mark that a service endpoint interface as defining a web service interface. All endpoint implementation classes MUST have a WebService annotation and must meet the requirements of section 3.3 of the JAX-WS 2.0 specification.@XmlRootElement --Maps a class or an enum type to an XML element. When a top level class or an enum type is annotated with the @XmlRootElement annotation, then its value is represented as XML element in an XML document. //Example: Code fragment @XmlRootElement class Point { int x; int y; Point(int _x,int _y) {x=_x;y=_y;} }

@XmlSeeAlso -- Instructs JAXB to also bind other classes when binding this class.Java makes it impractical/impossible to list all sub-classes of a given class. This often gets in a way of JAXB users, as it JAXB cannot automatically list up the classes that need to be known to JAXBContext.For example, with the following class definitions:

The user would be required to create JAXBContext as JAXBContext.newInstance(Dog.class,Cat.class) (Animal will be automatically picked up since Dog and Cat refers to it.)XmlSeeAlso annotation would allow you to write: @XmlSeeAlso({Dog.class,Cat.class}) class Animal {} class Dog extends Animal {} class Cat extends Animal {}

This would allow you to do JAXBContext.newInstance(Animal.class). By the help of this annotation, JAXB implementations will be able to correctly bind Dog and Cat.

Monday, March 30, 2009

Adding cache in seam is very easy, and the 2.1.1 release has even made using caching easier.

It is useful to cache html typically when you have lots of hits to the database, otherwise you shouldn't use html cache.

I recently needed to read the current url, extract a part of the url, and check the database for a hit on that pattern. This was done on every request and is something that suits caching. The data I was retrieving was something that was changed very rarely thus it could also be cached infinetly. For this purpose, I have chosen the in-built treecache that ships with JBoss and Seam.

Getting the url from a JSF page can be done like this:

HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();String uri = request.getRequestURI();// zero so that trailing empty strings will be discardedString[] values = uri.split("/", 0);//Concatinate the string and create a query based on the concatinated string

Note that the key must be something unique. In this example the key value will get the current url as a key, and in our web application this is unique, thus works excellent as a key. The s:cache will use the key to retrieve the value from its HashMap.s:cache uses pojoCache internally, but we want to configure it to use treecache and that is done in components.xml.You do this by defining the namespace

xmlns:cache="http://jboss.com/products/seam/cache"

and then

<cache:jboss-cache-provider configuration="META-INF/treecache.xml">

Furthermore, we have defined a region on the s:cache called instructionPageFragments. This can be configured in treecache.xml where we can define timeToLive maxAgeSeconds and so on.

<!-- Whether or not to fetch state on joining a cluster NOTE this used to be called FetchStateOnStartup and has been renamed to be more descriptive. --> <attribute name="FetchInMemoryState">true</attribute>

<!-- The max amount of time (in milliseconds) we wait until the initial state (ie. the contents of the cache) are retrieved from existing members in a clustered environment --> <attribute name="InitialStateRetrievalTimeout">20000</attribute>

<!-- Number of milliseconds to wait until all responses for a synchronous call have been received. --> <attribute name="SyncReplTimeout">20000</attribute>

<!-- Max number of milliseconds to wait for a lock acquisition --> <attribute name="LockAcquisitionTimeout">15000</attribute>

<!-- Name of the eviction policy class. --> <attribute name="EvictionPolicyClass"></attribute>

<!-- Indicate whether to use marshalling or not. Set this to true if you are running under a scoped class loader, e.g., inside an application server. Default is "false". --> <attribute name="UseMarshalling">false</attribute>

Since I want everything to be cached infinetly I have uncommented the regions out and put 0 (no limit) on the _default_ region

You can also programatically add and remove content to the cache.

@In private CacheProvider cacheProvider;

//Removing the cache with the region instructionPageFragments, and the key instruction-'current url'cacheProvider.remove("instructionPageFragments", "instruction-" + url);//Adding to the cachecacheProvider.put("instructionPageFragments", "instruction-" + url, "This text will be cached!!");

which doesnt hash the password which is what I did at first. The reason why I didnt start using md5 at once is because you needed a default username and password to be able to log into your seam application. And since I was using an import.sql script that created a default user for me, I had no way of knowing how to hash the password.

So what I needed to do is manually somehow hash a password which I could put in my import.sql script, so that I could enable hashing and correctly log in to my seam application. However this was easier said then done.I tried changing the @UserPassword(hash="md5") and try to log in, but for obvious reason the login failed, because it was expecting a hashed password.

So then I got the idea to call a method that doesn't require login, which creates a user for us, that is called from a button in the login page. However when I persisted the user, the password was saved as clear text. This baffled me, because I thought that seam would handle that automatically. But if you actually look at the user entity and the setHashPassword method, it is not annotated, and it only sets a string. So it was obvious it only persisted the password as string.In Seam you can also use IdentityManager to create a user for you. This will perform the hashing for you. So I tried to call

So apparently IdentityManager requires the correct permissions, which must be set in your drools setting in security.drl, but I didn't want to do that, since that is not how I wanted to configure my seam application.

So what I did, was look in the seam source and IdentityManager class and find the exact code that performs the hashing for us, and do that manually. And this worked great. Here is the source.

Note that the method saveProcessUser() is called from the user administration form, and the currentUser object is my User entity. Seam will inject all the methods for us, so we dont have to do that. So we check if the verifyPassword is set and correct and then we hash the password. If the @UserPassword is set to something other than none, then it will correctly save a user and you can finally copy the hashed password in your import.sql script.

PS: You first should have the @UserPassword(hash="none") and then go to your user registration and then just print out what the password is, and then copy that to your import.sql script. When the authentication correctly works with either md5 or sha, then you can safely add the user to the database.

This command will create an ant script under the directly build/client.Now go to build/client and type ant after setting $AXIS_HOME. This will generate FooService-test-client.jar which we now can use to retrieve data from the WebService in the client. I recommend changing the name to something more appropriate.

//Retrieve the List as an arrayFooCanonical[] get_return = stub.getFoo(fooImpl).getGetFooResponse().get_return();//Do what you want with the array

Note that even if you return a List from the WebService, you will get it as an array. But it is quite easy to put it in a List in the client afterwards. Also remember that the username and password is sendt in clear text, so you might want to send it through https, so it is encrypted.