Uploaded image for project: 'OpenWebBeans'
  1. OpenWebBeans
  2. OWB-703

getBeans cache key algorithm must be unique

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Critical
    • Resolution: Fixed
    • 1.1.4, 1.1.5
    • 1.1.6
    • None
    • None
    • OWB 1.1.4, Codi 1.0.5, MyFaces 2.0.13, Tobago 1.5.7

    Description

      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

      Attachments

        1. OWB-703-ordering-and-other-fixes.patch
          30 kB
          Udo Schnurpfeil
        2. OWB-703-refactored.diff
          2 kB
          Jean-Louis Monteiro
        3. OWB-703-2nd-shoot.patch
          2 kB
          Jean-Louis Monteiro
        4. OWB-703-hash-cache-as-integer.patch
          0.9 kB
          Udo Schnurpfeil
        5. owb-703.patch
          16 kB
          Udo Schnurpfeil

        Activity

          People

            struberg Mark Struberg
            lofwyr Udo Schnurpfeil
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: