[ https://issues.apache.org/jira/browse/OWB-703?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13454735#comment-13454735 ]
Udo Schnurpfeil commented on OWB-703: ------------------------------------- Computing the hash code in the constructor is a good idea for this class! The code is thread save automatically. But I would keep the hash code computation in a separate method to keep the code clean and comprehensible. > getBeans cache key algorithm must be unique > ------------------------------------------- > > Key: OWB-703 > URL: https://issues.apache.org/jira/browse/OWB-703 > Project: OpenWebBeans > Issue Type: Bug > Affects Versions: 1.1.4, 1.1.5 > Environment: OWB 1.1.4, Codi 1.0.5, MyFaces 2.0.13, Tobago 1.5.7 > Reporter: Udo Schnurpfeil > Assignee: Mark Struberg > Priority: Critical > Fix For: 1.1.6 > > Attachments: OWB-703-2nd-shoot.patch, > OWB-703-hash-cache-as-integer.patch, owb-703.patch > > > Our application was tested in a Pre-Production environment, and it turns out > a problem which occurs sometime after 2 weeks but sometimes after a short > time: > [9/11/12 10:46:27:288 CEST] 0000009e ServletWrappe E SRVE0068E: Uncaught > exception thrown in one of the service methods of the servlet: > FacesServlet. Exception thrown : java.lang.IllegalArgumentException: Given > bean type : class > org.apache.myfaces.extensions.cdi.jsf.impl.scope.conversation.ViewAccessConversationExpirationEvaluatorRegistry > is not applicable for the bean instance : BereitstellungModelLoaderImpl, > Name:BereitstellungModelLoader, WebBeans Type:MANAGED, API > Types:[java.lang.Object,de.nordlbit.iopc.optionen.jsf.model.BereitstellungModelLoader,de.nordlbit.iopc.optionen.jsf.model.BereitstellungModelLoaderImpl,java.io.Serializable], > > Qualifiers:[javax.inject.Named,javax.enterprise.inject.Any,javax.enterprise.inject.Default] > at > org.apache.webbeans.container.BeanManagerImpl.getReference(BeanManagerImpl.java:923) > at > org.apache.webbeans.container.InjectableBeanManager.getReference(InjectableBeanManager.java:133) > at > org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils.getContextualReference(CodiUtils.java:215) > at > org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils.getContextualReferenceByClass(CodiUtils.java:179) > at > org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils.getContextualReferenceByClass(CodiUtils.java:139) > at > org.apache.myfaces.extensions.cdi.jsf.impl.util.ConversationUtils.postRenderCleanup(ConversationUtils.java:668) > at > org.apache.myfaces.extensions.cdi.jsf2.impl.listener.phase.CodiLifecycleWrapper.render(CodiLifecycleWrapper.java:128) > at javax.faces.webapp.FacesServlet.service(FacesServlet.java:191) > at > com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1213) > [...] > I think the reason is, that two objects got the same key in the map. > So we got wrong objects. > After this exception the application must be restarted, no request works > anymore. > How can this happen? > Problem number 1: > Looking in the implementation: > There will be computed a key of type Long from all given parameters. > Parameters: injectionPointType, bdaBeansXMLPath, qualifiers > In practice we have one "injectionPointType" (say t) and one "qualifiers" > (say q) and the computed hash code will be: > key = hash(t) + 29 * hash(q) > assume: hash(t)=1000 and hash(q)=100 > we got a key of 1000 + 29 * 100 = 3900 > but that's the same like > 1029 + 29 * 99 = 3900 > 1058 + 29 * 98 = 3900 > 1087 + 29 * 97 = 3900 > and so on. > If we got parameter with hash(t)=1029 and hash(q)=99 we have found 2 beans > with the same key. > With that our map is broken, because the 2nd bean will remove the 1st bean > while adding (with the same key). > Problem number 2: > Hash codes are generally not suitable to be used as keys because there are > not unique. > The JavaDoc of the Object.hashCode() method says: > "It is not required that if two objects are unequal according to the > equals(Object) method, > then calling the hashCode method on each of the two objects must produce > distinct integer results." > The strings "org.apache.kcmdjx" and "java.lang.Object" have the same hash > code (at least in my Apple java VM). > Solution: > I see 3 solutions here: > Solution 1: > Do the same like in 1.1.3: Build a String with all information inside. > Disadvantage: slow > Solution 2: > Create an helper object, which contains the unconverted information analog to > e.g.: org.apache.myfaces.tobago.internal.context.ClientPropertiesKey > This will be faster than string concatenation, but there is to create an > object as well. > Solution 3: > Using a map which can handle more than one key. > E. g. org.apache.commons.collections.map.MultiKeyMap -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators For more information on JIRA, see: http://www.atlassian.com/software/jira