Skip to content

Support property placeholders in url attribute of @HttpExchange #28492

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
xuan opened this issue May 20, 2022 · 2 comments
Closed

Support property placeholders in url attribute of @HttpExchange #28492

xuan opened this issue May 20, 2022 · 2 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Milestone

Comments

@xuan
Copy link

xuan commented May 20, 2022

Affects: 6.0.0-SNAPSHOT


Hi Spring Team,

Can you please add the ability to reference properties for @HttpExchange, @GetExchange, and @PostExchange defined in application.yaml?

Right now, I have to hard code my URL in the annotation:

@HttpExchange(url = "/multitenant/public/api")
public interface CumulusRepository {

    @GetExchange("/get_stuff")
    Cumulus getCumulusAlerts(@RequestHeader Map<String, String> headers);

    @PostExchange("/getAccessToken")
    Token getAccessToken(@RequestBody String credential);
}

But I wish to define my URL in application.yaml and reference it in the annotations like this:

@HttpExchange(url = "${cumulus.baseUrl}")
public interface CumulusRepository {

    @GetExchange("${cumulus.alertUrl}")
    Cumulus getCumulusAlerts(@RequestHeader Map<String, String> headers);

    @PostExchange("${cumulus.tokenUrl}")
    Token getAccessToken(@RequestBody String credential);
}
@xuan xuan changed the title Add support for system properties for @HttpExchange, @GetExchange, and @PostExchange Add support for system properties for @HttpExchange, @GetExchange, and @PostExchange for spring-boot-starter-web 3.0.0-SNAPSHOT May 20, 2022
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label May 20, 2022
@rstoyanchev rstoyanchev self-assigned this May 20, 2022
@rstoyanchev rstoyanchev added type: enhancement A general enhancement in: web Issues in web modules (web, webmvc, webflux, websocket) and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels May 20, 2022
@rstoyanchev rstoyanchev added this to the 6.0.0-M5 milestone May 20, 2022
@rstoyanchev rstoyanchev changed the title Add support for system properties for @HttpExchange, @GetExchange, and @PostExchange for spring-boot-starter-web 3.0.0-SNAPSHOT Add support for system properties in url of @HttpExchange methods May 20, 2022
@sbrannen sbrannen changed the title Add support for system properties in url of @HttpExchange methods Add support for system properties in URL of @HttpExchange methods May 20, 2022
@sbrannen sbrannen changed the title Add support for system properties in URL of @HttpExchange methods Support property placeholders in URL attribute for @HttpExchange May 20, 2022
@rstoyanchev rstoyanchev changed the title Support property placeholders in URL attribute for @HttpExchange Support property placeholders in url attribute of @HttpExchange May 23, 2022
@jcthalys
Copy link

jcthalys commented Dec 2, 2022

This is still not working for me:

// using spring boot 3.0.0 and framework 6.0.2
@SpringBootApplication
public class HttpInterfaceApplication {

	public static void main(String[] args) {
		SpringApplication.run(HttpInterfaceApplication.class, args);
	}

	@Bean
	ApplicationListener<ApplicationReadyEvent> ready(GoogleClient googleClient) {
		return event -> {
			String googlePage = googleClient.getGooglePage();
			System.out.println(googlePage);
		};
	}

	@Bean
	GoogleClient googleClient(HttpServiceProxyFactory factory) {
		return factory.createClient(GoogleClient.class);
	}

	@Bean
	HttpServiceProxyFactory getHttpServiceProxyFactory(WebClient.Builder builder) {
		return HttpServiceProxyFactory.builder()
				.clientAdapter(WebClientAdapter.forClient(builder.build())).build();
	}
}

@HttpExchange(url = "${google.url}")
interface GoogleClient {
	@GetExchange
	String getGooglePage();
}

Error:

java.lang.IllegalArgumentException: Map has no value for 'google.url'
	at org.springframework.web.util.UriComponents$MapTemplateVariables.getValue(UriComponents.java:348) ~[spring-web-6.0.2.jar:6.0.2]
	at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:263) ~[spring-web-6.0.2.jar:6.0.2]
	at org.springframework.web.util.HierarchicalUriComponents$FullPathComponent.expand(HierarchicalUriComponents.java:921) ~[spring-web-6.0.2.jar:6.0.2]
	at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:439) ~[spring-web-6.0.2.jar:6.0.2]
	at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:52) ~[spring-web-6.0.2.jar:6.0.2]
	at org.springframework.web.util.UriComponents.expand(UriComponents.java:161) ~[spring-web-6.0.2.jar:6.0.2]
	at org.springframework.web.util.DefaultUriBuilderFactory$DefaultUriBuilder.build(DefaultUriBuilderFactory.java:391) ~[spring-web-6.0.2.jar:6.0.2]
	at org.springframework.web.util.DefaultUriBuilderFactory.expand(DefaultUriBuilderFactory.java:149) ~[spring-web-6.0.2.jar:6.0.2]
	at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultRequestBodyUriSpec.uri(DefaultWebClient.java:228) ~[spring-webflux-6.0.2.jar:6.0.2]
	at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultRequestBodyUriSpec.uri(DefaultWebClient.java:189) ~[spring-webflux-6.0.2.jar:6.0.2]
	at org.springframework.web.reactive.function.client.support.WebClientAdapter.newRequest(WebClientAdapter.java:105) ~[spring-webflux-6.0.2.jar:6.0.2]
	at org.springframework.web.reactive.function.client.support.WebClientAdapter.requestToBody(WebClientAdapter.java:69) ~[spring-webflux-6.0.2.jar:6.0.2]
	at org.springframework.web.service.invoker.HttpServiceMethod$ResponseFunction.lambda$initBodyFunction$5(HttpServiceMethod.java:378) ~[spring-web-6.0.2.jar:6.0.2]
	at org.springframework.web.service.invoker.HttpServiceMethod$ResponseFunction.execute(HttpServiceMethod.java:288) ~[spring-web-6.0.2.jar:6.0.2]
	at org.springframework.web.service.invoker.HttpServiceMethod.invoke(HttpServiceMethod.java:105) ~[spring-web-6.0.2.jar:6.0.2]
	at org.springframework.web.service.invoker.HttpServiceProxyFactory$HttpServiceMethodInterceptor.invoke(HttpServiceProxyFactory.java:271) ~[spring-web-6.0.2.jar:6.0.2]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.2.jar:6.0.2]
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:218) ~[spring-aop-6.0.2.jar:6.0.2]

When I use the url directly it works fine

@renatomrcosta
Copy link

renatomrcosta commented Dec 2, 2022

This is still not working for me:

I stumbled in the same issue, and found out perhaps a clue to clarify if the URL field considers application properties at all, or just URI placeholders.

This error indicates that the application properties with placeholders are not considered at all: If you try, it just considers it a path: (like when you call "/v1/api/customer/{customerId}". The $ sign in java or \$ in Kotlin were not parsed.

@HttpExchange(url = "{httpbin}") // I chose a single name here, because if we try to simply remove the braces and add the $ back, it still doesn't work, but it's easy enough to use to test.
interface HttpBinClient {
    @GetExchange("/anything")
    fun anything(@PathVariable("httpbin") httpbin: String): Mono<String>
}

(Repo with working example here: LINK)

so, in this case: is it truly intended that the URL and other fields can be parameterized with application properties at all? If so, then this ticket shouldn't be closed as completed.

Otherwise @jcthalys , I recommend taking the more verbose approach of providing a webClient with its baseUrl set per httpProxyFactory you need to build for the time being, and not setting the URL property at the annotation level. It's the approach I'll be taking for the time being.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

5 participants