Help

Controls

PermLinkWikiLink
Switch Workspace

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.

Forum: Seam Users Forum ListTopic List
09. Nov 2009, 21:05 America/New_York | Link

I am tired of running into so many gotchas in seam so I am going to start a list here and keep it going so I can refer back to it. hopefully it helps others as well. (yes, these are personal opinions).

  1. Do NOT use s:convertEntity if you are using a Session action bean and a form. See http://seamframework.org/Documentation/DropdownBoxesWithEntitiesAndPageScope for more info. OR do NOT use pulldowns unless you are in a conversation is the other way to go.
  2. Add required=false to every @In @Out attribute (or your clustering will break since there is no seam session at time of clustering)
  3. Do NOT use entityMgr.merge as it gets you into trouble time after time. Use if(bean.getId != null) entityMgr.persist(bean) instead
  4. DO lookup your bean at the start of every conversation or if in a session with entityMgr.find(Bean.class, bean.getId()) so you don't end up in trouble.
  5. Do make sure that s:button is in an h:form or clustering for just that button will NOT work but it will work with clustering off
  6. Please vote on https://jira.jboss.org/jira/browse/JBSEAM-4460 as the conversation is already in progress error is very annoying. Most of the time, we don't care that a conversation is in progress and want to end the previous conversation if one exists.
  7. DO make sure you have a good grasp on proxies vs. instances in hibernate and when debugging pay very good attention as seam is sometimes comparing a proxy to an instance and failing validation because of that :(.

This is the list off the top of my head. I will continue to post as I run into the previous issues I have run into before. I know there are around 15 gotchas in seam that you have to be careful of.

Seam does rock!! just has some issues that I want to keep track of. Feel free to add your list here as well.

30 Replies:
09. Nov 2009, 22:12 America/New_York | Link

How about:

  1. Do not use EAR/EJBs if you want ZeroTurnaround, use WAR/POJOs. Read more
  2. Do not use JPA if you want full ZeroTurnaround
  3. Do not use JBossAs 4.x if you want your application to do cold restarts fast during development (for example if you decided to use JPA) (Don't know if 5.x starts faster, if it does not, revert to plain Tomcat)
  4. Do not use EmbeddedJBoss if you want your tests to run fast (just delete the jboss .jars from your test project and and use Spring to get to you datasource)
  5. Do not use JSF/Richfaces 3.x without http compression enabled because it generates a huge amount of XHML that will take a lot of time to download and your users will get angry, enable tomcat http compression, if your admin refuses to let you do it, use a filter
  6. Do not validate simple stuff (numeric fields, regular expressions, dates, simple comparisions between fields, etc) using seam/jsf/richfaces validation, it is very slow, and your users will not like it, use jQuery, only use seam/jsf/richfaces validation for complex business logic stuff.
  7. Do not trust seam-gen CRUD, the code it generates is wrong.
  8. If you are using Richfaces, always work with the global queue enabled it will save you lots of could not acquire lock on @Synchronized component headaches
  9. If you are Richfaces global queue do not believe it is going to solve all your concurrency problems, if you need stability fast, use ConfigurableSynchronizationInterceptor with a big default value (around 1 minute). Read more

And those are only the ones I can think from the top of my head...

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

Rating:  * * * * *
09. Nov 2009, 23:24 America/New_York | Link

great additions. I just ran into a new one.

Do NOT bother using rich:comboBox with s:selectItems s:convertEntity and s:convertEnum...you are wasting your time, wait for JIRA issue.... https://jira.jboss.org/jira/browse/RF-5046 which should support it(vote on the issue too!!!) I would have used this widget for every pulldown if it worked better.

09. Nov 2009, 23:40 America/New_York | Link

Nice things, I especially like Francisco Peredo list. I think maybe this list should have a better place... (maybe sticky).

10. Nov 2009, 00:38 America/New_York | Link

Thanks for the list guys, others and myself really appreciate it! And Franciso I really like your quote where or from whom is it from?

10. Nov 2009, 00:55 America/New_York | Link

definitely sticky this thread!

 

Java EE 6 + RevCo = distributed rock stardom!

10. Nov 2009, 03:29 America/New_York | Link

Nelson Mandella in his inaugural speech 1994.

10. Nov 2009, 12:09 America/New_York | Link

Really good gotchas lists Dean, and Francisco!! Thread should be sticky and lists added to the knowledge base.

 

Please, rate when you find a useful answer!

10. Nov 2009, 13:03 America/New_York | Link

Here is some of mine:

1. Force IE8 to run in IE7 mode because of bug in JSF/Seam/Facelets

<page view-id="*">
    <header name="X-UA-Compatible">IE=EmulateIE7</header>

2. Remember that @WebRemote and jpdl.xml does not use your custom defined Message Bundle, it uses the default one even if you have configured to use custom in faces-config.xml. See here

3. Links of files using s:link inside seam pdf if you download and open the pdf in pdf viewer (ie adobe reader), then the servlet path will be replaced with file:///project/. You have to hardcode the a href with the servlet path together with the slink.

<s:link action="#{fileHandler.downloadById()}" value="#{file.name}" propagation="none">
	 <f:param  name="fileId" value="#{file.id}"/>
</s:link>
 <a href="#{servletPath.path}?fileId=#{file.id}&amp;actionMethod=#{path.replace('/','')}%2Fstatus%2Fstatus_pdf.xhtml%3AfileHandler.downloadById()&amp;" >download</a>

Where servletPath.path returns correct url to your server ie: http://localhost:8080/whatever

4. Hibernate does not care about ordering of your entity beans for creation of tables. So if you have create-drop in your persistence.xml and something in import.sql that requires ordering of rows in table to be correct, then you must have created the table before and not let hibernate create it for you. Link.

10. Nov 2009, 19:25 America/New_York | Link

Hi Dean,

Thanks for compiling this, I did run into some of them as well. I have some questions, though, as some of the statements require them.

Add required=false to every @In @Out attribute (or your clustering will break since there is no seam session at time of clustering)

Can you be more specific? What do you mean by the time of clustering? When the server or the application are being started up? Or during a failover?

Do NOT use entityMgr.merge as it gets you into trouble time after time. Use if(bean.getId != null) entityMgr.persist(bean) instead

Again, can you be more specific? I've been using merge() for many months and have had no problems once I understood how it works (which, granted, is not intuitive: the old entity is read, non-transient fields are copied into it from the updated entity then the old entity is saved).

Do make sure that s:button is in an h:form or clustering for just that button will NOT work but it will work with clustering off

What do you mean clustering for the button? Load balancing of the call to the underlying session bean? The failover of the same call?

10. Nov 2009, 21:05 America/New_York | Link
Add required=false to every @In @Out attribute (or your clustering will break since there is no seam session at time of clustering)

if you set yours up for clustering, seam luckily replicates the session AFTER the page loads(unlike some impls which if session replication fails, your page does not load). anyways, if you have the default which is true, session replication fails on that bean constantly(stateful beans of course...not sure if it matters or not on stateless ones...it shouldn't but don't know for sure until I see it with my own eyes)

Do make sure that s:button is in an h:form or clustering for just that button will NOT work but it will work with clustering off

I had an h:commandButton and a s:button on one page and we would fail one node, click the h:commandButton and it failed over successfully. The same scenario and clicking s:button however fails in a clustered environment.

Do NOT use entityMgr.merge as it gets you into trouble time after time. Use if(bean.getId != null) entityMgr.persist(bean) instead

We have had multiple situations with merge screwing things up. One of them was this... http://seamframework.org/Community/StaleStateExceptionAfterUpdateSuccessAndTxIsDone

Also, this may be a good post for some other people(more a hibernate issue though I think as it would be nice if hibernate filed in the top level exception message with the details of eery getNextSQLException for you.... http://www.seamframework.org/102758.lace

We had other merge problems as well we ran into where after a merge you have a proxy but the data model(ie. someOtherBean.getchild() had the instance(and these guys are not equal!!!!) Later, if you have a list of things and the selected one is a proxy and the one in the list of items is an instance, you get dang value is not valid errors. After throwing merge away, we have never had any problems since then!!! I am sure eventually you will run into a situation ;).

11. Nov 2009, 00:52 America/New_York | Link

This post should be a sticky post.

11. Nov 2009, 01:03 America/New_York | Link

em.merge() is a crude operation that is not recommended (or even necessary) if you are using SMPC and HMF and as a result the PC does not close during the LRC. You should only merge() entities into the PC if they are detached. They do not become detached if you use SMPC and Hibernate manual flush. Read SiA for more on this...

sticky this thread!

oh, and what about (ab)use of (or lack thereof?) of @BypassInterceptors. Some of these comments will become historical/irrelevant for Seam 3 with the injection of Weld as the new Seam core (e.g. no more interceptors and no more contextual variables).

 

Java EE 6 + RevCo = distributed rock stardom!

Rating:  * * * * *
11. Nov 2009, 01:07 America/New_York | Link

Don't forget (ab)use of the rendered attribute in JSF tags. DAllen covers this here:

http://www.jsfcentral.com/articles/speed_up_your_jsf_app_1.html

 

Java EE 6 + RevCo = distributed rock stardom!

11. Nov 2009, 02:30 America/New_York | Link

I find the biggest problem is invoking an action no matter what validation failures occur without loosing all the values a user has entered, e.g. deleting a row in a data table but keeping the values for all the other rows. Solution is here.

11. Nov 2009, 17:19 America/New_York | Link

Arbi Sookazian, thanks for shedding more light on the merge.....it is no wonder I love hibernates previous saveOrUpdate then as that is what I really want to do...I could care less about reattaching an entity to the conversation.

12. Nov 2009, 00:21 America/New_York | Link
Arbi Sookazian wrote on Nov 11, 2009 01:07:
Don't forget (ab)use of the rendered attribute in JSF tags. DAllen covers this here: http://www.jsfcentral.com/articles/speed_up_your_jsf_app_1.html

This is a very important one if you are trying to speed up your app. His research was quite eye opening. I am now much more careful about what I put in my rendered attributes!

04. Mar 2010, 19:19 America/New_York | Link

adding one more in here. DO DO DO Run these tests before going to production

Test 1: 1. startup your server connected to database(do not hit a single web page yet!!!!) 2. pull the ehternet cable between db and server 3. hit a web page(many configurations end up waiting infinitely for db to respond)

Test 2: (fails in oracle, passes in postgres) 1. startup your server connected to database 2. login and go to some page that can be refreshed without needing the database(and preferably with input) 3. crash the database with kill -9 4. refresh the page(it should work) 5. enter data into the page and submit(it should go to your error.xhtml page)

On #5 Oracle ends up in infinite redirect.

BIG NOTE: On Test 2, if you use go to the login page after db is down and login, seam will only refresh the login page with Transaction failed even though I would prefer it to also go to errorDbDown.xhtml like my other pages...it is quite weird(seam 2.2.0.GA)

LASTLY, even though postgres worked fine on crashing, ONE MORE test everyone should run is this

Test 3. 1. After test 2, bring back up the database 2. make sure your website is still working

I have been having trouble with Test 3 in postgres/tomcat config but i thinkt that may be the connection pool is hibernates even though I keep trying to swap to c3p0 and failing.

later, Dean

04. Mar 2010, 19:21 America/New_York | Link

adding one more in here. DO DO DO Run these tests before going to production

Test 1: 1. startup your server connected to database(do not hit a single web page yet!!!!) 2. pull the ehternet cable between db and server 3. hit a web page(many configurations end up waiting infinitely for db to respond)

Test 2: (fails in oracle, passes in postgres) 1. startup your server connected to database 2. login and go to some page that can be refreshed without needing the database(and preferably with input) 3. crash the database with kill -9 4. refresh the page(it should work) 5. enter data into the page and submit(it should go to your error.xhtml page)

On #5 Oracle ends up in infinite redirect.

BIG NOTE: On Test 2, if you use go to the login page after db is down and login, seam will only refresh the login page with Transaction failed even though I would prefer it to also go to errorDbDown.xhtml like my other pages...it is quite weird(seam 2.2.0.GA)

LASTLY, even though postgres worked fine on crashing, ONE MORE test everyone should run is this

Test 3. 1. After test 2, bring back up the database 2. make sure your website is still working

I have been having trouble with Test 3 in postgres/tomcat config but i thinkt that may be the connection pool is hibernates even though I keep trying to swap to c3p0 and failing.

later, Dean

05. Mar 2010, 02:20 America/New_York | Link

As per popular request, I've made this a sticky.

17. Mar 2010, 22:16 America/New_York | Link

new article on dzone: Event-Driven MVC with JSF and JBoss Seam - Common Pitfalls: http://java.dzone.com/articles/event-driven-mvc-jsf-and-jboss

I don't necessarily agree with all the author's points in the above dzone article.

e.g. Scenario 1 - Placing controller initiation code in the facelets. I don't see anything wrong with this if you do it the right way. An example of the right way is showing h:commandButton which invokes an init() method and when the page reRenders, the button is not rendered.

e.g. Scenario 2 - Placing data retrieval methods in the facelets. What's wrong with this in the situation of populating a rich:dataTable via @DataModel List<T>? I guess this scenario is showing the problem with data retrieval (i.e. hitting the db) via rendered attribute. This actually is a practice or pattern to avoid generally in JSF apps.

 

Java EE 6 + RevCo = distributed rock stardom!

12. Apr 2010, 22:50 America/New_York | Link

Not sure if this is already posted but be careful the names of variables you use when you inject an EJB:

http://seamframework.org/Community/EJBAndInjection#comment123992

inject using interface name then Seam component name.

Example:

@Name("smartComponent")
@Stateless
public class SmartBean implements ISmart {
...
}

inject SmartBean into DumbBean:

@Name("dumbComponent")
@Stateless
public class DumbBean implements IDumb {
    @In
    private ISmart smartComponent;
}
 

Java EE 6 + RevCo = distributed rock stardom!

14. Apr 2010, 00:02 America/New_York | Link
Francisco Peredo wrote:

6). Do not validate simple stuff (numeric fields, regular expressions, dates, simple comparisions between fields, etc) using seam/jsf/richfaces validation, it is very slow, and your users will not like it, use jQuery, only use seam/jsf/richfaces validation for complex business logic stuff.

Are you talking only about a4j validation that occurs when tabbing off an input tag, or are you also including validation that occurs when clicking the submit button?
22. Apr 2010, 14:05 America/New_York | Link

Remember that if you have a component and you are using @Roles and you have listeners on that component, it will be called N + 1 (N being roles and 1 being @Name) times according to how many @Role names you use.

@Name("systemlogListener")
@Transactional
@Scope(ScopeType.SESSION)
@Role(name="esbLogListener", scope=ScopeType.EVENT )
public class SystemlogListener implements Serializable {

@Observer("storeSystemlog")
    public void saveSystemlog(String description, String category, String username, String org) {
    	//Save some stuff
    }
}

Then you call the event.

Events.instance().raiseEvent("storeSystemlog");
//This will now get called twice(!) because @Role will create a new component
23. Apr 2010, 20:44 America/New_York | Link
Steve Jagels wrote on Apr 14, 2010 00:02:
Are you talking only about a4j validation that occurs when tabbing off an input tag, or are you also including validation that occurs when clicking the submit button?

Both, if you are only validating numeric fields, regular expressions, dates, simple comparisions between fields, etc using a4j:validation will result in a this takes too much time perception from your user, if you think it, it makes sense: why travel all the way to the server to know if ABC is a number when you can do that in the client with javascript?

 

Please don't forget to rate!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint Exupéry

Please visit my blog

08. May 2010, 19:33 America/New_York | Link
Both, if you are only validating numeric fields, regular expressions, dates, simple comparisions between fields, etc using a4j:validation will result in a this takes too much time perception from your user, if you think it, it makes sense: why travel all the way to the server to know if ABC is a number when you can do that in the client with javascript?

Because the client can't be trusted?

15. May 2010, 22:29 America/New_York | Link

I find that there are (at least) three gotchas pertaining to MANUAL flushing.

  1. Queries cause a flush either way so your flush logic might get interrupted in the middle of a conversation!
  2. If you build up nested conversations your actions should investigate whether or not they are apart of a nested conversation to ensure that they don't call flush() on behalf of the parent-conversation.
  3. Other stuff depends on transactions and are not aware of MANUAL flushing, such as JMS. This means that your application will be out of sync because transaction doesn't behave like they used to.

I've covered them in more detail on my blog, kasper.eobjects.org.

15. May 2010, 23:38 America/New_York | Link
Francisco Peredo wrote on Nov 09, 2009 22:12:
How about:
  1. Do not use EAR/EJBs if you want ZeroTurnaround, use WAR/POJOs. Read more

This is no longer true as of JRebel 3: https://community.jboss.org/wiki/JRebel3withSeam2xtutorial

 

Java EE 6 + RevCo = distributed rock stardom!

15. May 2010, 23:43 America/New_York | Link
Kasper Sørensen wrote on May 15, 2010 22:29:
Queries cause a flush either way so your flush logic might get interrupted in the middle of a conversation!

Simply use the setFlushMode() method to set to COMMIT as a workaround to this problem: http://java.sun.com/javaee/5/docs/api/javax/persistence/Query.html#setFlushMode%28javax.persistence.FlushModeType%29

The reason the MANUAL flush mode type is not in the JPA API is mostly political (Oracle's Mike Keith will not allow)...

 

Java EE 6 + RevCo = distributed rock stardom!

18. May 2010, 07:32 America/New_York | Link
Queries cause a flush either way so your flush logic might get interrupted in the middle of a conversation!

Odd, we usually do one query in the first transaction and it didn't flush our changes. we had to manually call flush. Also, once we were bootstrapped into the object model, we go from page to page to page to page never calling flush and then at the end call flush and we see all the updates go. We have log4jdbc running in production and even had an issue from two conversations on the same data where the second one got an exception as it had stale data(it did inserts at the end instead of updates)....fixed that by clearing the entityManager BUT point being we have no updates to the db during a 5 to 10 question script the agents read to customers.

We usually go from object to object(which results in queries to db and no flush)...I think there are cases where we do queries in the middle too....I guess I have just never seen that behavior yet in our cases.( not sure it is a gotcha)

27. May 2010, 15:57 America/New_York | Link

This is very important: Do not use @Out with Stateless Session Bean or any stateless beans, it could be a memory leak!!!!

The Stateless session bean is not bound with any context, and it tend to be reused cross different users, Seam BijectionInterceptor doesn't clean up the @Out attribute references after invocation of the method. so the SLSB hold the references until next it called by other users, so even if the context is already invalid, the JVM still think the variable is still being used and can't release it to GC.

If you configured EJB has max 250 instances, then chances are you may have 250 different copies of attributes should be released and still in the memory for each Stateless EJB.

To avoid this you can either

@In(required = false)

in front of @Out, or use

ScopeType.CONVERSATION.getContext().set("variable name", variable)

; I prefer the second way, it faster and cleaner. This will be more safer and clean (actually it is code I stole from the component method).