Jirmed
Jirmed

Reputation: 441

How to create YAML DSL route in Apache Camel to query LDAP properties?

I am trying to create a YAML Route to perform a simple query to a LDAP server and to output the result to the log. My route looks like following:

- route:
    id: route-561c
    from:
      uri: timer:1000
      id: from-c523
      parameters:
        repeatCount: 1
      steps:
        - setBody:
            id: setBody-1772
            expression:
              simple:
                expression: '{"filter":"(sn=Amanda)"}'
                id: simple-12b7
                resultType: String
        - unmarshal:
            id: unmarshal-7216
            json:
              id: json-91b8
              library: Jackson
        - log:
            message: ${body[filter]}
            id: log-eab5
        - to:
            uri: spring-ldap:ldapTemplate
            id: to-60b7
            parameters:
              operation: SEARCH
        - log:
            message: ${body}
            id: log-18a8
            logName: logLdapResponse
- beans:
    - name: ldapContextSource
      properties:
        url: ldap://localhost:389
        base: ou=Users,dc=example,dc=org
        userDn: cn=admin,dc=example,dc=org
        password: admin
      type: org.springframework.ldap.core.support.LdapContextSource
    - name: ldapTemplate
      type: org.springframework.ldap.core.LdapTemplate

When running the route I receive following error:

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2023-04-21T12:24:23.642+02:00 ERROR 26712 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.apache.camel.spring.boot.CamelSpringBootInitializationException: java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.ldap.core.support.LdapContextSource': **At least one server url must be set**
    at org.apache.camel.spring.boot.CamelSpringBootApplicationListener.onApplicationEvent(CamelSpringBootApplicationListener.java:212) ~[camel-spring-boot-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.spring.boot.CamelSpringBootApplicationListener.onApplicationEvent(CamelSpringBootApplicationListener.java:58) ~[camel-spring-boot-4.0.0-M1.jar:4.0.0-M1]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176) ~[spring-context-6.0.8.jar:6.0.8]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169) ~[spring-context-6.0.8.jar:6.0.8]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143) ~[spring-context-6.0.8.jar:6.0.8]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:413) ~[spring-context-6.0.8.jar:6.0.8]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:370) ~[spring-context-6.0.8.jar:6.0.8]
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:937) ~[spring-context-6.0.8.jar:6.0.8]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:587) ~[spring-context-6.0.8.jar:6.0.8]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[spring-boot-3.0.6.jar:3.0.6]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[spring-boot-3.0.6.jar:3.0.6]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[spring-boot-3.0.6.jar:3.0.6]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1304) ~[spring-boot-3.0.6.jar:3.0.6]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1293) ~[spring-boot-3.0.6.jar:3.0.6]
    at net.konzult.camel.ldappoc.LdapPocApplication.main(LdapPocApplication.java:10) ~[classes/:na]
Caused by: java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.ldap.core.support.LdapContextSource': At least one server url must be set
    at org.apache.camel.dsl.yaml.deserializers.BeansDeserializer$1.configure(BeansDeserializer.java:70) ~[camel-yaml-dsl-deserializers-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.dsl.yaml.common.YamlSupport$1.configure(YamlSupport.java:121) ~[camel-yaml-dsl-common-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.dsl.yaml.YamlRoutesBuilderLoader$1.doConfigure(YamlRoutesBuilderLoader.java:174) ~[camel-yaml-dsl-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.dsl.yaml.YamlRoutesBuilderLoader$1.configure(YamlRoutesBuilderLoader.java:148) ~[camel-yaml-dsl-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.builder.RouteBuilder.checkInitialized(RouteBuilder.java:724) ~[camel-core-model-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.builder.RouteBuilder.configureRoutes(RouteBuilder.java:666) ~[camel-core-model-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.builder.RouteBuilder.addRoutesToCamelContext(RouteBuilder.java:598) ~[camel-core-model-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.impl.engine.AbstractCamelContext.addRoutes(AbstractCamelContext.java:1201) ~[camel-base-engine-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.main.RoutesConfigurer.addDiscoveredRoutes(RoutesConfigurer.java:237) ~[camel-main-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.main.RoutesConfigurer.configureRoutes(RoutesConfigurer.java:212) ~[camel-main-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.spring.boot.CamelSpringBootApplicationListener.onApplicationEvent(CamelSpringBootApplicationListener.java:106) ~[camel-spring-boot-4.0.0-M1.jar:4.0.0-M1]
    ... 14 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.ldap.core.support.LdapContextSource': At least one server url must be set
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770) ~[spring-beans-6.0.8.jar:6.0.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[spring-beans-6.0.8.jar:6.0.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.8.jar:6.0.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:365) ~[spring-beans-6.0.8.jar:6.0.8]
    at org.apache.camel.spring.spi.SpringInjector.newInstance(SpringInjector.java:64) ~[camel-spring-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.spring.spi.SpringInjector.newInstance(SpringInjector.java:41) ~[camel-spring-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.support.PropertyBindingSupport.resolveBean(PropertyBindingSupport.java:1545) ~[camel-support-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.dsl.yaml.deserializers.NamedBeanDefinition.newInstance(NamedBeanDefinition.java:64) ~[camel-yaml-dsl-deserializers-4.0.0-M1.jar:4.0.0-M1]
    at org.apache.camel.dsl.yaml.deserializers.BeansDeserializer$1.configure(BeansDeserializer.java:68) ~[camel-yaml-dsl-deserializers-4.0.0-M1.jar:4.0.0-M1]
    ... 24 common frames omitted
Caused by: java.lang.IllegalArgumentException: At least one server url must be set
    at org.springframework.ldap.core.support.AbstractContextSource.afterPropertiesSet(AbstractContextSource.java:417) ~[spring-ldap-core-3.0.2.jar:3.0.2]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1816) ~[spring-beans-6.0.8.jar:6.0.8]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766) ~[spring-beans-6.0.8.jar:6.0.8]
    ... 32 common frames omitted

I understand that the problem is the part At least one server url must be set. But the bean has a property with url is included.

The entire project can be found on https://github.com/jirmed/ldap-poc . The demo OpenLdap server can be started in Docker using docker compose up in the subfolder ldap

EDIT 1:

As suggested by @FedericoMariani I removed the beans from the yaml and added the LDAP configuration in the application.properties file

#LDAP
spring.ldap.base:ou=Users,dc=example,dc=org
spring.ldap.password:admin
spring.ldap.urls:ldap://localhost:389
spring.ldap.username:cn=admin,dc=example,dc=org

I have pushed the modification to higher stated github repository.

Now Camel reaches and queries the OpenLDAP server but I get a new error:

023-04-23T14:06:36.755+02:00  WARN 28704 --- [ - timer://1000] o.a.camel.component.timer.TimerConsumer  : Error processing exchange. Exchange[4A1AE7CEFE694EC-0000000000000000]. Caused by: [org.springframework.ldap.NameNotFoundException - [LDAP: error code 32 - No Such Object]]

org.springframework.ldap.NameNotFoundException: [LDAP: error code 32 - No Such Object]
        at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:183) ~[spring-ldap-core-3.0.2.jar:3.0.2]
        at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:386) ~[spring-ldap-core-3.0.2.jar:3.0.2]
        at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:338) ~[spring-ldap-core-3.0.2.jar:3.0.2]
...

In the log of OpenLDAP I there is:

openldap  | 64451f4c conn=1020 fd=12 ACCEPT from IP=172.27.0.1:38336 (IP=0.0.0.0:389)
openldap  | 64451f4c conn=1020 op=0 BIND dn="cn=admin,dc=example,dc=org" method=128
openldap  | 64451f4c conn=1020 op=0 BIND dn="cn=admin,dc=example,dc=org" mech=SIMPLE ssf=0
openldap  | 64451f4c conn=1020 op=0 RESULT tag=97 err=0 text=
openldap  | 64451f4c conn=1020 op=1 SRCH base="ou=Users,dc=example,dc=org,ou=Users,dc=example,dc=org" scope=2 deref=3 filter="(sn=amanda)"
openldap  | 64451f4c conn=1020 op=1 SEARCH RESULT tag=101 err=32 nentries=0 text=
openldap  | 64451f4c conn=1020 op=2 UNBIND
openldap  | 64451f4c conn=1020 fd=12 closed

I beliveve the problem is in base="ou=Users,dc=example,dc=org,ou=Users,dc=example,dc=org" where the base is stated twice.

If i try to call the same LDAP with same query from another (non Camel) java project that works withou errors the same line in the OpenLDAP log is:

openldap  | 644520ca conn=1021 op=1 SRCH base="ou=Users,dc=example,dc=org" scope=2 deref=3 filter="(&(objectClass=inetOrgPerson)(sn=amanda))"

EDIT 2:

As stated in the comment by @FedericoMariani there is a bug in dependency camel-spring-ldap-starter version 4.0.0-M2. Commenting out the base property and moving it to the search filter string works as a workaround.

Upvotes: 0

Views: 1654

Answers (1)

Federico Mariani
Federico Mariani

Reputation: 11

since you are using spring boot, is spring boot AutoConfiguration viable for you? In case you can:

  • add org.apache.camel.springboot:camel-spring-ldap-starter dependency to your pom
  • Remove beans configuration in yaml routes
  • Add spring.ldap.* properties in application.properties (urls, base, embedded.base-dn, password, username...) in order to AutoConfigure the ldapTemplate bean

Since camel spring boot delegates the creation of org.springframework.ldap.core.support.LdapContextSource to spring boot itself an additional check is executed, therefore the error

At least one server url must be set

I hope this solution works for you, in the meantime, we will review how beans are created from yaml so that karavan and yaml dsl can offer the same experience on all runtimes.

Upvotes: 1

Related Questions