I am looking for a way to disable spring batch's skip-limit, I tried specifying a value of "0" for skip-limit, but is not accepting. Here is my use case:
My batch.xml has skip-limit="${limit_val}"
I want to set ${limit_val} to 0, meaning fail on any exception by default. On seeing the failure, I can look at the reason and decide if its ok to skip the record. If skippable, I want to be able to override ${limit_val} with a value of, say 1 and re-run the batch.
Any help on how this can be achieved?
Have you tried using skip-policy property?
In chunk under step define skip-policy="mySkipPolicy" and then give definition of skipPolicy bean.
Provide skipPolicy bean implementation by implementing SkipPolicy Interface.
public class MySkipPolicy implements SkipPolicy
{
private int limit;
public boolean shouldSkip(final Throwable t, final int skipCount) throws SkipLimitExceededException
{
return true or false based on skipCount;
}
}
Related
Indeed, this is somewhat a duplicate of a previous question, however I was wondering whether, after nine years and some new specification versions being published, the situation has changed in any way, or whether at least a non portable way to solve this problem exists (I mean: does Hibernate Validator allow to do this, even if the API does not?).
The question is: is there a way I can make my custom constraint validator detect the validation groups that were passed to the validator instance causing the validation to occur, by inspecting the ConstraintValidatorContext?
Example, suppose I have my bean:
public class MyBean {
#MyConstraint(value = 5, groups = V1.class)
#MyConstraint(value = 10, groups = {V2.class, V3.class})
private int foo;
// cut
}
and a validator call:
validator.validateValue(MyBean.class, "foo", 7, V2.class);
can my constraint validator detect that V2.class validation group was requested, in this specific case?
public class MyConstraintValidator implements ConstraintValidator<MyConstraint, Integer> {
// cut
#Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
Class<?>[] requestedValidationGroups = // expected {V2.class} here, in case of the above call
}
}
In the initialize method I can get an information about the static declaration of the constraint annotation, so in the above example I could get {V1.class} or {V2.class, V3.class} depending on which of the two constraints the implementation detects as the one being applied. However, I would need to get just {V2.class} in this case.
Is it possible in some way?
Looking at Hibernate Validator 6.0 sources, I see I would need access to org.hibernate.validator.internal.engine.ValueContext<T, V>, in particular its currentGroup property, but neither this group nor the ValueContext itself is passed to the Hibernate Validator constraint validator context implementation implementation (org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl), whose creation, on the other hand, seems not to be customisable (there's a direct new ConstraintValidatorContextImpl(...) call in org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree.validateConstraints(ValidationContext<T>, ValueContext<?, ?>, Set<ConstraintViolation<T>>)).
Any further hint?
Question is : how can I handle a chain of fallback values in Spring expression, allowing me to fallback on higher level configuration until I got a defined value ?
To explain a little, let's illustrate this with my own use case : I was intending to create a Spring application using the #Scheduled annotation to run some processes. Thing is I have many scheduled tasks and I would let the running frequency to be easily configurable for all of them, or only for a subset.
So I was looking for something like
#Component
public class SpecificTaskRunner {
#Scheduled(cron = "${ specific-task-cron ?: task-families-cron ?: default-cron }")
public void specificTask() {
doSomething();
}
}
Letting application configure either the frequency of all the Scheduled task at once by overriding the default-cron value, or only a subset of them by overriding the task family property, or finally, specifying on a task basis. Advantage of this approach is that it allows to play with multiple configuration levels as every scheduled task looks for the appropriate property starting from the most specific, and looking for a more generic until it got something defined, ultimately fall-backing on a default global value.
Unfortunately... this do not work. When evaluated, if the first element is not defined, then if fallback on the whole remaining. In this example, it would mean that if configuration misses a value for specific-task-cron, then the resolved value is : task-families-cron ?: default-cron which unfortunately is not what I'm looking for!
I found 2 way to handle it :
The first one, is purely based on Spring expression. Spring seems to re-evaluates the result of the Elvis operator if it also is a Spring expression. So my working configuration was :
#Component
public class SpecificTaskRunner {
#Scheduled(cron = "${ specific-task-cron ?: ${ task-families-cron ?: default-cron }}")
public void specificTask() {
doSomething();
}
}
Which in my real use case, with one more fallback, was not really convenient...
So I switched to a simpler solution that relies on configuration by defining a chain of values this way :
#application.yml
default-cron: '0 */5 0 0 0 0' #every 5 minutes
task-families-cron: ${default-cron}
specific-task-cron: ${task-families-cron}
Combined with
#Component
public class SpecificTaskRunner {
#Scheduled(cron = "${specific-task-cron}")
public void specificTask() {
doSomething();
}
}
This way any override of a property apply to hierarchical sub-levels, unless they got themselves overridden.
Both solutions seems to works, so at the end, yes Spring expression language handle multiple fallback. Whether it should be used, or is the configuration approach better readable... I let you decide.
I'd like to learn if there are some rules / conditions that a Spring component is wrapped (proxied) by CGLIB. For example, take this case:
#Component
public class TestComponent {
}
#Service
//#Transactional(rollbackFor = Throwable.class)
public class ProcessComponent {
#Autowired
private TestComponent testComponent;
public void doSomething(int key) {
// try to debug "testComponent" instance here ...
}
}
If we let it like this and debug the testComponent field inside the method, then we'll see that it's not wrapped by CGLIB.
Now if we uncomment the #Transactional annotation and debug, we'll find that the instance is wrapped: it's of type ProcessComponent$$EnhancerByCGLIB$$14456 or something like that. It's clearly because Spring needs to create a proxy class to handle the transaction support.
But I'm wondering, is there any way that we can detect how and when does this wrapping happen ? For example, some specific locations in Spring's source code to debug into to find more information; or some documentations on the rules of how they decide to create a proxy.
For your information, I need to know about this because I'm facing a situation where some component (not #Transactional, above example is just for demonstrating purpose) in my application suddenly becomes proxied (I found a revision a bit in the past where it is not). The most important issue is that this'll affect such components that also contain public final methods and another issue (also of importance) is that there must have been some unexpected changes in the design / structure of classes. For these kind of issues, of course we must try to find out what happened / who did the change that led to this etc...
One note is that we have just upgraded our application from Spring Boot 2.1.0RELEASE to 2.1.10RELEASE. And checking the code revision by revision up till now is not feasible, because there have been quite a lot of commits.
Any kind of help would be appreciated, thanks in advance.
You could debug into org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(Class, String, TargetSource).
If any advisor is found, the bean will be proxied.
If you use a #Lookup method injection it will also proxy the component class.
Can Spring's caching framework be made aware of the authentication status of the request context, or is it easier to roll your own caching solution?
Regardless of the fact I find the use case super weird, you can condition caching for pretty much anything that works with SpEL. And since you can call any method you want with SpEL, you're good to go.
I realized that it is harder than it should but the following works. First create a static method that does your check (you can use the SecurityContextHolder for that)
public class SecurityChecker {
public static boolean isSecured() {
// Whatever
return SecurityContextHolder.getContext().getAuthentication() != null;
}
}
Then in your annotated method, specify the following (assuming myCache should be affected):
#Cacheable(cacheNames = "myCache", condition = "T(com.example.SecurityChecker).isSecured()")
public Foo doIt(String key) { ... }
There's two problems currently:
You can't create a meta-annotation to avoid repeating the condition attribute over and over again (see SPR-13475)
The SpEL setup does not allow you to easily call a method on a bean (which would be nicer than calling a static method). I've just created SPR-13812 for that
This (obviously) works:
#Every("10s")
public class Extinguisher extends Job {
...
}
...but this doesn't:
#Every(Play.configuration.getProperty("my.setting", "10s"))
public class Extinguisher extends Job {
...
}
When running auto-test, the app doesn't start and complains my controllers can't get enhanced because of a NullPointerException encountered by javassist.
Is there a way to configure a job scheduling from application.conf?
You can schedule your job manually from #OnApplicationStartup job:
#OnApplicationStartup
public class ExtinguisherBootstrap extends Job {
public void doJob() {
new Extinguisher()
.every(Play.configuration.getProperty("my.setting", "10s"));
}
}
I don't know whether Play or javassist extend what you can do with the Java language, but I can at least point out that the following line is not legal Java:
#Every(Play.configuration.getProperty("my.setting", "10s"))
For an annotation with a parameter with type T and value V, the Java Language Specification requires that:
If T is a primitive type or String, V is a constant expression
In this case, T, the type of the annotation parameter, is a String, but the value you're trying to set to it isn't a (compile-time) constant expression.
The issue is that "configuration" wont be available at that stage.
I don't think what you want to do is possible (as per my current knowledge of Play, maybe someone knows a trick to make it work)
You may be able to "hack it" by having a job run every few seconds and in that job launch the target job as per configuration. It's less efficient, but it may solve your issue
You can do something like this:
#On("cron.noon")
Which will look for a line like this in application.conf:
cron.noon = 1s