Mule
  1. Mule
  2. MULE-5955

AbstractAnnotatedTransformerArgumentResolver returns a jaxbContext the first time only even when it should not

    Details

    • Type: Patch submission Patch submission
    • Status: Closed
    • Priority: Critical Critical
    • Resolution: Won't Fix or Usage Issue
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Modules: (other)
    • Labels:
      None
    • User impact:
      Low
    • Configuration:
      Hide

      <mule xmlns="http://www.mulesoft.org/schema/mule/core"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:spring="http://www.springframework.org/schema/beans"
      xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
      xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml"
      xmlns:mongo="http://www.mulesoft.org/schema/mule/mongo"
      xsi:schemaLocation="
      http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.1/mule.xsd
      http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/3.1/mule-vm.xsd
      http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/3.1/mule-xml.xsd
      http://www.mulesoft.org/schema/mule/mongo http://www.mulesoft.org/schema/mule/mongo/1.0/mule-mongo.xsd
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      ">

      <mulexml:jaxb-context name="jaxbContext" packageNames="org.mule.entity"/>
      <mulexml:jaxb-object-to-xml-transformer name="jaxbTransformer" jaxbContext-ref="jaxbContext" />

      <mongo:config name="mongo" database="test" host="localhost" port="27017"/>

      <flow name="testJaxbAndMongo">
      <vm:inbound-endpoint address="vm://test" exchange-pattern="request-response"/>
      <logger level="ERROR" message="#[payload]"/>
      <mongo:update-objects collection="test-collection" config-ref="mongo" multi="false" upsert="true"
      query="

      { "id" : #[json:id] }

      " element="#[payload]" />
      </flow>
      </mule>

      Show
      <mule xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:spring="http://www.springframework.org/schema/beans" xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" xmlns:mongo="http://www.mulesoft.org/schema/mule/mongo" xsi:schemaLocation=" http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.1/mule.xsd http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/3.1/mule-vm.xsd http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/3.1/mule-xml.xsd http://www.mulesoft.org/schema/mule/mongo http://www.mulesoft.org/schema/mule/mongo/1.0/mule-mongo.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd "> <mulexml:jaxb-context name="jaxbContext" packageNames="org.mule.entity"/> <mulexml:jaxb-object-to-xml-transformer name="jaxbTransformer" jaxbContext-ref="jaxbContext" /> <mongo:config name="mongo" database="test" host="localhost" port="27017"/> <flow name="testJaxbAndMongo"> <vm:inbound-endpoint address="vm://test" exchange-pattern="request-response"/> <logger level="ERROR" message="# [payload] "/> <mongo:update-objects collection="test-collection" config-ref="mongo" multi="false" upsert="true" query=" { "id" : #[json:id] } " element="# [payload] " /> </flow> </mule>
    • Similar Issues:
      MULE-1530Dynamic routing using StaticRecipientList only succeeds on first occurance - only when component has a return object
      MULE-2645TemplateEndpointRouter alters template values of endpoints only for the first time
      MULE-6162AbstractMessageReceiver returns value even when endpoint exchange pattern is one-way
      MULE-5529jaxb-xml-to-object-transformer returns only a jaxb object and not the type specified as the returntype
      MULE-7178JAXBContext defined in app, later on using xpath in Mule expression, leading to exception
      MULE-5537jaxb-xml-to-object-transformer needs the jaxbContext-ref set even though in the documentation it says it needs not to be
      MULE-751JdbcUtils.getParams returns null when root is a Map, even if there is a property with the correct name on endpoint
      MULE-7152When using cxf:proxy-service with a wsdl having multiple ports, the proxy only redirects the first one.
      MULE-2216Request Merge transition is available even when not logged in
      MULE-7611MEL expression using dot notation .'variable-name' always returns null if first value at first access is null, even after value changes

      Description

      Mongo db connector has a property upsert (boolean) on the update-objects element. The auto generated code will try to find a transformer to convert from string to boolean to get the proper value from the XML configuration. This works fine until you introduce a Jaxb context to your Mule configuration. Once you add a jaxb context, a JAXBContextResolver will start appearing in the list of transformer resolvers. When Mule tries to find a transformer to convert String to Boolean, the first time only the jaxb resolver will return a jaxb context to be used by the transformer for the conversion. Obviously this will throw an exception when the transformer is eventually invoked. Second time round however, everything works fine because the JAXBContextResolver returns null!!

      The issue is found in the AbstractAnnotatedTransformerArgumentResolver. In the resolve, if the arguments are not correctly annotated, the classes are added correctly to the nonMatchingClasses set so that next time round we return null immediately without having to scan. However, the first time round, the context is still returned even though the arguments are not properly annotated!! Second time round, everything works fine because the argument classes would be in the nonMatchingClasses and a null is immediately returned.

      1. patch.txt
        0.8 kB
        Alan Cassar

        Activity

        Hide
        Alan Cassar added a comment -

        Attached test case

        Show
        Alan Cassar added a comment - Attached test case
        Hide
        Alan Cassar added a comment -

        Attached patch

        Show
        Alan Cassar added a comment - Attached patch
        Hide
        Alan Cassar added a comment -

        To run this test, you need mongo db running. Also just wanted to note that this does not happen only with mongodb connector

        Show
        Alan Cassar added a comment - To run this test, you need mongo db running. Also just wanted to note that this does not happen only with mongodb connector
        Hide
        Daniel Feist added a comment -

        Any chance you can convert this into a test without external dependencies?

        Show
        Daniel Feist added a comment - Any chance you can convert this into a test without external dependencies?
        Hide
        Alan Cassar added a comment -

        new testcase without external dependencies

        Show
        Alan Cassar added a comment - new testcase without external dependencies
        Hide
        Alan Cassar added a comment -

        Hi dan, I added a new test without any external dependencies. I debugged this a little further and found out why in most cases it works, but it does not with the mongo db connector (and possibly a lot more other cloud connectors).

        The code generated by the cloud connector, for example for an attribute like upsert which is boolean, the cloud connector generates code to convert the string from the xml to boolean, however, it does not use java.lang.Boolean, but it uses the primitive boolean.

        When the JAXBTransformerResolver class gets a jaxb context, it will try to check whether the source/target are jaxb annotated, hence it will call method hasJaxbAnnotations(). The problem here is that since boolean is primitive, the call String p = annotatedType.getPackage().getName(); will throw an exception.

        In my opinion there are two ways of fixing this, either by applying the patch I attached here yesterday, which will return null immediately when the JAXBTransformerResolver tries to get the context, or otherwise the hasJaxbAnnotations() class need to check not just for the ignore packages, but also for primitive types.

        Hope all of this helps.

        Show
        Alan Cassar added a comment - Hi dan, I added a new test without any external dependencies. I debugged this a little further and found out why in most cases it works, but it does not with the mongo db connector (and possibly a lot more other cloud connectors). The code generated by the cloud connector, for example for an attribute like upsert which is boolean, the cloud connector generates code to convert the string from the xml to boolean, however, it does not use java.lang.Boolean, but it uses the primitive boolean. When the JAXBTransformerResolver class gets a jaxb context, it will try to check whether the source/target are jaxb annotated, hence it will call method hasJaxbAnnotations(). The problem here is that since boolean is primitive, the call String p = annotatedType.getPackage().getName(); will throw an exception. In my opinion there are two ways of fixing this, either by applying the patch I attached here yesterday, which will return null immediately when the JAXBTransformerResolver tries to get the context, or otherwise the hasJaxbAnnotations() class need to check not just for the ignore packages, but also for primitive types. Hope all of this helps.

          People

          • Assignee:
            Unassigned
            Reporter:
            Alan Cassar
          • Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development