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.
| Online: | 15 Members of 9400 |
| Forum: Seam Users |
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).
conversation is already in progresserror 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.
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.
How about:
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
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.
Nice things, I especially like Francisco Peredo list. I think maybe this list should have a better place... (maybe sticky).
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?
definitely sticky this thread!
Java EE 6 + RevCo = distributed rock stardom!
Nelson Mandella in his inaugural speech 1994.
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!
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}&actionMethod=#{path.replace('/','')}%2Fstatus%2Fstatus_pdf.xhtml%3AfileHandler.downloadById()&" >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.
My blog
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.
Can you be more specific? What do you mean by ? When the server or the application are being started up? Or during a failover?
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).
What do you mean ? Load balancing of the call to the underlying session bean? The failover of the same call?
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)
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.
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 ;).
This post should be a sticky post.
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 of Weld as the new Seam core (e.g. no more interceptors and no more contextual variables).
Java EE 6 + RevCo = distributed rock stardom!
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!
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.
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.
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!
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
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
As per popular request, I've made this a sticky.
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!
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!
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?
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 componentMy blog
Both, if you are only validating numeric fields, regular expressions, dates, simple comparisions between fields, etc using a4j:validation will result in a perception from your user, if you think it, it makes sense: why travel all the way to the server to know if 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
Because the client can't be trusted?
I find that there are (at least) three gotchas pertaining to MANUAL flushing.
I've covered them in more detail on my blog, kasper.eobjects.org.
This is no longer true as of JRebel 3: https://community.jboss.org/wiki/JRebel3withSeam2xtutorial
Java EE 6 + RevCo = distributed rock stardom!
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!
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)
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 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).