Spring Integration service-activator referencing Hibernate JPA repository method

I'm trying to use a Hibernate JPA repository method as the method for a service-activator. The definition within the chain looks like the following.

<int:chain input-channel="bootstrapLineupCdsStart" output-channel="bootstrapLineupItemCdsStart">
    <int:service-activator ref="lineupRepository" method="findByIntegrationStatusNew" />
    <int:filter expression="!payload.isEmpty()" discard-channel="bootstrapLineupItemCdsStart"/>
    <int:splitter expression="payload"/>
    <int:service-activator ref="lineupServicePipeline" method="createLineup"/>
    <int:aggregator/>
</int:chain>

The offending line is the first service-activator, specifically this line <int:service-activator ref="lineupRepository" method="findByIntegrationStatusNew" />

For the sake of completeness here is the repository class itself

@Repository( "lineupRepository" )
public interface LineupRepository extends JpaRepository<LineupEntity, Integer> {
    @Query("select l from LineupEntity l where l.integrationStatus = 0")
    List<LineupEntity> findByIntegrationStatusNew();
}

Now because of the magic of spring/hibernate I don't actually implement the findByIntegrationStatusNew myself; this is dynamically implemented by the framework at runtime. I also don't need to explicitly define the lineupRepository bean as the @Repository annotation handles this for me.

As a result of the above I get the following exeption.

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.integration.handler.MessageHandlerChain#9$child#0.handler': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Target object of type [class com.sun.proxy.$Proxy79] has no eligible methods for handling Messages.

Finally, I do have a work around in place that seems to get the job done; it is an obvious work around and I suspect shouldn't be necessary. The work around consists of creating a new bean, explicitly defining the bean in the context XML and calling that method instead of the method on repository. So my work around looks a bit like this; first the workaround's context looks like this instead.

<int:chain input-channel="bootstrapLineupCdsStart" output-channel="bootstrapLineupItemCdsStart">
    <int:service-activator ref="lineupRepositoryService" method="findByIntegrationStatusNew" />
    <int:filter expression="!payload.isEmpty()" discard-channel="bootstrapLineupItemCdsStart"/>
    <int:splitter expression="payload"/>
    <int:service-activator ref="lineupServicePipeline" method="createLineup"/>
    <int:aggregator/>
</int:chain>
<bean id="lineupRepositoryService" class="com.mypackage.LineupRepositoryService"/>

Notice the first service-activator now references LineupRepositoryService instead of LineupRepository, and I also added a new bean definition.

Second in the work around, of course, I also defined a LineupRespositoryService class that looks like the following.

public class LineupRepositoryService {
    @Autowired
    private LineupRepository lineupRepository;

    public List<LineupEntity> findByIntegrationStatusNew() {
        return lineupRepository.findByIntegrationStatusNew();
    }
}

The workaround works, but I'd rather do it the right way. So anyone know how I can get it to properly work or what is going on here?

Upvotes: 1

Views: 714

Answers (1)

Artem Bilan
Artem Bilan

Reputation: 121552

@JeffreyPhillipsFreeman, we confirm with the test-cases that it is an issue from Spring Integration reflection method invocation perspective.

Need to fix it anyway: https://jira.spring.io/browse/INT-3820.

Mean while there is only a workaround like your service wrapper.

Upvotes: 1

Related Questions