spring-cloud-function icon indicating copy to clipboard operation
spring-cloud-function copied to clipboard

Document public API of adapters

Open Clockwork-Muse opened this issue 7 years ago • 6 comments

I'm assuming that it's Azure and its runtime that are instantiating AzureSpringFunctionInitializer/AzureSpringBootRequestHandler, which is also why you're required to have a no-arg constructor.

I'd like to be able to inject dependencies into my handlers, but this currently isn't possible, because the base initializer/handler is instantiated outside of Spring's control. Neither field injection nor setter injection seem to be used.

(Specifically, I'm trying to do my own JSON de/serialization and validation, because allowing Azure to do it gives you a 500, not a 400, if there are any validation problems.)

Clockwork-Muse avatar Mar 02 '18 18:03 Clockwork-Muse

We can definitely autowire the handler. Actually we already do. So what did you try that didn't work?

What is your function method signature? How do you ask for raw data to do your own JSON schlepping?

dsyer avatar Mar 08 '18 15:03 dsyer

I was just having the handler give me a string, but it looks like Azure closed the loophole - it deserializes any JSON object if Content-Type is set, which means it rejects objects before they even get to the runtime (which is kinda nice, in that it wouldn't charge you, but the problem is that currently they return absolutely the wrong status code and a completely unhelpful error message. And since I never see it, I can't return a standardized message, either).

In any case, given a small wireable dependency:

@Component
public class LocalWired {
    public int getValue() {
        return 5;
    }
}

... and the handler:

public class FooHandler extends AzureSpringBootRequestHandler<Foo, Bar> {

	@Autowired
	private LocalWired wired;

	public Bar execute(Foo foo, ExecutionContext context) {
		context.getLogger().log(Level.WARNING, wired == null ? "Not wired" : "Correctly autowired");
		return handleRequest(foo, context);
	}

}

... then Not wired is being logged.

Clockwork-Muse avatar Mar 08 '18 17:03 Clockwork-Muse

....I'm kicking myself, because I just realized this is dependent on the initialize method being called, which means the dependency is available.... after handleRequest is called. So I need to adjust how I wrote stuff, mostly. Maybe this just needs to be documented better?

Clockwork-Muse avatar Mar 08 '18 17:03 Clockwork-Muse

Maybe. I thought of it as an implementation detail though (users shouldn’t need to be aware). Wouldn’t it make more sense to inject the LocalWired into your function?

dsyer avatar Mar 08 '18 17:03 dsyer

I have other stuff I was injecting into my function, what I was using at this layer was the deserialization/error handling.

Deserialization, at least, needed to happen at this point, because since I have multiple functions they all need different signatures so they can be picked up (say, a GET and a POST would most likely return the same object, meaning the difference comes from the parameters). The moment you do your own deserialization you also need to handle the errors from it, which meant the error handling had to be there as well.

Clockwork-Muse avatar Mar 08 '18 18:03 Clockwork-Muse

I guess you need to call initialize() before the handler then? It would be easier with a concrete sample.

dsyer avatar Mar 08 '18 18:03 dsyer

Starting with version 4.0.x, the SCF Azure Adapter uses dependency injections and allows auto-wiring any Spring dependencies in your Azure function handlers.

tzolov avatar Jul 21 '23 14:07 tzolov