2

I'm struggling to use the configuration variables in the spring project to inject values other than String in the annotations. Is there a way to inject them?
The annotations require Integer and long values, but when injecting from application.yml, it is considered as String.

See the example below:

@Scheduled(fixedRate = "${scheduler.fixedrate:10}")
public void init(){}

The error is:

Incompatible types. Found: 'java.lang.String', required: 'long'

Any solution?

9
  • Does this answer your question? Commented Oct 11, 2023 at 20:15
  • @Jorn, No, the Value annotation does the cast itself. Commented Oct 11, 2023 at 20:30
  • Wait, is the type of the annotation value fixedRate a long itself? Then this is never going to work. You cannot use a Spring property to provide that value. Commented Oct 11, 2023 at 20:32
  • exactly. The field is long. I'm looking for a solution to it. There should be a solution. It doesn't make sense that this feature is only implemented for String values!! Commented Oct 11, 2023 at 20:34
  • What doesn't make sense is trying to assign a String to a long and expecting Spring to magically fix it. Commented Oct 11, 2023 at 20:35

3 Answers 3

4

There is no solution, simply because the specification doesn't allow it. In short that is how annotations work. The values for attributes have to adhere to the type they are defined in, and a String isn't a long.

The value substition is a Spring feature and which is why for certain annotations there is also a *String parameter to work around this. Which is why the @Scheduled has the fixedRateString property to work around this. It is a String and the String is parsed by Spring as an expression and thus you can resolve the value at runtime to the value you want to use.

This all is build into Spring for annotations that are created by Spring, it will not work for annotations not under the control of Spring or simply for values that aren't of type String.

So the basic answer to your question is there is no solution! Not the answer you wanted to hear but the answer nonetheless.

Sign up to request clarification or add additional context in comments.

Comments

2

To understand why it is not possible we need to understand how and what Spring does when you do something like this:

@Scheduled(fixedRateString = "${scheduler.fixedrate:10}")
public void init(){}

The string ${scheduler.fixedrate:10} was assigned to fixedRateString and won't get replaced by the value in your application.yml. You maybe thought fixedRateString would get the actual value from your application.yml which is not the case, it simply gets the value you configured.

Now when your application starts, Spring will interpret this string and then resolves it to your value in the application.yml and use it to setup scheduling, so this replacement happens at runtime and NOT at compile-time, this is the key point.

You wrote There should be a solution. It doesn't make sense that this feature is only implemented for String values. which is not entirely correct. It is not tied to string values, just the key of the property you define in the annotation is a string but the actual value of the property can be of any type.

Preprocessors What you probably want is a preprocessor which processes the source files before they get compiled (like C has one). But Java has no such preprocessor. Furthermore, it would not be possible for Spring, to implement such a preprocessor if Java would provide such a possibilty. The reason is, that values of properties are determined at runtime, as the application.yml is not the only place where one can configure properties. So even if Java would support preprocessors, there is no way to replace the key with the actual value as the value cannot be determined at compile time.

3 Comments

So Strings are not compile time constraints? and we can't define Integer and long in application.yml?
Strings are compile time constant. But they get resolved at runtime by spring, the resolved value could also be an integer or a long. What you want is something like a preprocessor, which replaces the string by the actual value before the code gets compiled but such a preprocessor does not exist and is also not possible, as the actual value cannot be determined during compile time as values for a property might be supplied during runtime.
I edited my comment and tried to explain what Spring actually does which might help to understand why its not possible what you want.
0

The @Scheduled annotation also has a fixedRateString property:

    /**
     * Execute the annotated method with a fixed period between invocations.
     * <p>The time unit is milliseconds by default but can be overridden via
     * {@link #timeUnit}.
     * @return the period as a String value &mdash; for example, a placeholder
     * or a {@link java.time.Duration#parse java.time.Duration} compliant value
     * @since 3.2.2
     */
    String fixedRateString() default "";

1 Comment

Thank you for your answer, but my point is how to use variables from the application.yml as integer and long. The Scheduled annotation is an example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.