Task scheduling using cron expression from properties file - cron

I have written a cron job:
#Scheduled(cron="${process.virtual.account.start}")
public void ecomProcessVirAccOrderPaymentsScheduler() {
LOGGER.info("Start --->" + this.getClass().getCanonicalName() + ".ecomProcessVirAccOrderPaymentsScheduler() Method");
schedulerJobHelper.ecomProcessVirAccOrderPaymentsScheduler();
LOGGER.info("End --->" + this.getClass().getCanonicalName() + ".ecomProcessVirAccOrderPaymentsScheduler() Method");
}
I want to get the cron attribute used with #Scheduled annotation to be populated from a external properties file. Currently I am fetching it from a property file inside the application scope.
I am able to fetch the value, but not able to use it with #Schedule annotation.

it is working in spring boot.
#Scheduled(cron="${cronExpression}")
private void testSchedule() {
System.out.println("Helloooo");
}
in application.properties I have a property like this as below:
cronExpression=* * * ? * *

Which version of spring framework are you using? This won't work if it is less than 3.0.1.
Bug Report here in Spring 3.0.0 and it has been fixed in 3.0.1.
So if you are using Spring 3.0.1 or greater then following things you have to do to use in cron expression
Make an entry in applicationContext.xml for PropertyPlaceHolderConfigurer class that is
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:ApplicationProps.properties</value>
</list>
</property>
</bean>
After That Use it in using the #Scheduled method like
Update: In case if you are using spring boot no need to do anything, below code excerpt should work.
#Scheduled(cron="${instructionSchedularTime}")
public void load(){
}
Note: fixed delay and fixed-rate cann't take property value from placeholder because they take long value. Cron attribute take argument as String so you can use placeholder for that.

You can assign value directly from property file, i'm using spring boot BTW
#Scheduled(cron = "${com.oracle.fusion.cron}")
public void getInvoiceInterfaceHeader() {
}

Try something like
#Configuration
#PropertySource("/path/to/file")
public class LoadPropertiesFile{
//Other project configurations
}
For more, click here

For me works in that way:
"#{${cronExpression}}

Related

Extending AbstractCassandraConfiguration is ignoring application.yml auto configuration

I'm using spring-boot-starter-data-cassandra-reactive(version 3.2.4) and have provided all the spring.data.cassaandra properties is application.yml. It works fine. But I need to add some customCassandraConversion so I extended AbstractCassandraConfiguration. The moment I extend AbstractCassandraConfiguration the application.yml aka the CassandraAutoConfiguration stops working. Is there another way to to configure customConversions without overriding AbstractCassandraConfiguration. Or how can I get both working? I'm using spring-boot 2.5.4
You can register your custom conversions as a Bean in config and they'll be picked up by AbstractCassandraConfiguration.
#Bean
public CassandraCustomConversions customConversions() {
// Add your converters here
List<?> converters = Arrays.asList(...)
return new CassandraCustomConversions(convert));
}

Mule Issue : More than one JAXBContext

We are facing one issue in our Mule Adapter related to JAXB context, needed some opinion on the same
We are using xpath to evaluate some expressions in the choice blocks in our adapter like below for instance,
<choice doc:name="Choice">
<when expression="//env:abc/env:Body/ref:dataelement/ref:/ref:element" evaluator="xpath">
......
</when>
Now, this works perfectly fine in our application but the problem arises when one of other team uses this Adapter as a jar in their application.
When they try to use this adapter, they are getting below error,
Message : More than one object of type class javax.xml.bind.JAXBContext registered but only one expected.
Type : org.mule.api.registry.RegistrationException
Code : MULE_ERROR--2
JavaDoc : http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/registry /RegistrationException.html.
After debugging with the help of loggers etc, we narrowed down to the choice block used above which is causing this particular issue. Also, googled a bit and found one of the posts pointing out the same issue.
Also, to confirm we commented out the choice block having xpath expression and the flow went ahead but broke again where was xpath used in some other way.
https://www.mulesoft.org/jira/browse/MULE-5926
Can anyone please suggest any suitable workaround to resolve this issue?
I agree with you. It is an unresolved issue in Mule.
One solution we have implemented is not define the jaxb context in the config you are providing in the jar file.
Along with the jar file, give instructions to the end application using it, to include the JAXB packages in their JAXB Context object definition.
This way there will be only one JAXB context and it will work smoothly.
Hope this helps.
This is a bit late however the solution that worked was
<mulexml:jaxb-context name=“JAXB_Context“ packageNames=“org.example.test1:org.example.test2“ doc:name=“JAXB Context1“ />
Please note that there must be no space between package names.
Thanks to: http://dominikbial.de/quicktipp-working-with-more-than-one-package-name-in-a-jaxb-context-config-in-mule-esb/
As of now we cannot add more than one JAXBContext in mule. As an alternative you can write your custom transformer.
I implemented something like
public interface MyAppJaxbObj2XmlComponent<I,O> extends
MyAppComponent<I,O>,Callable {
public O marshal(I input) throws Exception;
}
Abstart transformer
public abstract class AbstractMyAppJaxbObj2XmlComponent<I,O> implements
MyAppJaxbObj2XmlComponent<I,O>{
private Class<I> inputType;
public AbstractMyAppJaxbObj2XmlComponent(){
this.inputType = (Class<I>) new TypeToken<I>(getClass())
{}.getRawType();
}
public AbstractMyAppJaxbObj2XmlComponent(Class<I> type){
this.inputType = type;
}
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
I input = eventContext.getMessage().getPayload(inputType);
O output = marshal(input);
return output;
}
}
Your flow transformer this will load your needed jaxb during startup.
#Component
public class MyFlowJaxbObj2XmlComponent extends
AbstractMyAppJaxbObj2XmlComponent<RequestPayloadType,String> {
#PostConstruct
public void init() {
//Load your schema during startup
}
}
You can also implement a fluid interface as an alternative for this.

Spring Integration: Error Injecting a QueueChannel in a Bean to calculate RemainingCapacity

I want to inject a QueueChannel in a bean so that I could monitor the RemainingCapacity of it. It would be great if any one can guide me to fix this.
Below is my Config:
<si:channel id="queueChannel">
<si:queue capacity="200"/>
</si:channel>
<bean id="inboundAdapterPollingConfiguration" class="com.foo.impl.InboundAdapterPollingConfigurationImpl">
<property name="channel" ref="queueChannel"/>
<property name="jdbcInboundAdapter" ref="jdbcInboundAdapter"/>
</bean>
Bean Code:
public class InboundAdapterPollingConfigurationImpl implements MethodInterceptor{
QueueChannel channel;
public QueueChannel getChannel() {
return channel;
}
public void setChannel(QueueChannel channel) {
this.channel = channel;
}
}
Error:
java.lang.IllegalStateException: Cannot convert value of type
[$Proxy336 implementing org.springframework.integration.core.PollableChannel,
org.springframework.integration.MessageChannel] to required type
[org.springframework.integration.channel.QueueChannel]
for property 'channel': no matching editors or conversion strategy found
When you enable JMX, channels, endpoints etc get wrapped in a proxy; this means you can only inject them using an interface (such as MessageChannel). We are looking at options to make this a little easier in the future but, for now, you have to unwrap the proxy to get access to the underlying QueueChannel object. Here is a Gist showing how to do it.
John, in the our chat you said:
I am using the JMX Export to get the info about the TaskExecutors in my application and to modify it dynamically
So, there is no need to fight with proxy for your case, because <int-jmx:mbean-export> has attribute managed-components () and you can just list bean nemas of your executors.
Your queueChannel won't be a proxy.

Using MOXy's #XmlCDATA annotation with jersey

I'm working on REST web-service written with jersey and I'm trying to output some XML with CDATA sections in it. I understand the reference implementation of JAXB doesn't support that, so I've downloaded EclipseLink's MOXy and I'm trying to get the #XmlCDATA annotation to work.
My JAXB mapped bean looks like this
package com.me.entities;
#XmlRootElement #XmlAccessorType(XmlAccessType.FIELD)
public class MyBean {
#XmlAttribute
private URI thumbnail;
#XmlElement(name="longdescription") #XmlCDATA
private String description;
public MyBean() { }
public final String getDescription() { return description; }
public final void setDescription(String d) { this.description = d; }
}
and I have the jaxb.properties file in the com/me/entities along with the class files. The properties file has
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
in it. I'm sure it gets loaded successfully since if I replace the factory class name with some nonsense the app breaks down. Also, explicitly marshaling the file creating the JAXBContext on my own works fine, so the problem seems related to jersey. According to this my setup is fine, but when my jersey resource returns an instance of MyBean
...
#GET #Produces(MediaType.TEXT_XML)
public MyBean getMyBean() {
MyBean b = new MyBean();
b.setDescription("Some blurb plenty of invalid chars like <<< && >>>");
return b;
}
what I get back has no CDATA in it, but looks like
<?xml version="1.0" encoding="UTF-8"?>
<info><longdescription>Some blurb plenty of invalid chars like <<< && >>></longdescription></info>
What am I doing wrong?
Looks like the problem was my application server: I am running this with WebLogic 10.3.5 in development mode, which comes with a lot of common libraries pre-installed that in the default configuration take precedence over those deployed in the webapp WEB-INF/lib folder.
To fix this a weblogic specific application description is needed, just create a weblogic.xml file inside WEB-INF containing the prefer-web-inf-classes option. The file I used is this:
<?xml version='1.0' standalone='yes'?>
<weblogic-web-app>
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
</weblogic-web-app>
I still have no idea which library was the problem though, anyone knows feel free to edit this answer.
Please download Jaxb Extension:
This is Eclipselink open source extension for Jaxb.
Get jar file: eclipselink.jar copy into Project lib.
http://www.eclipse.org/eclipselink/downloads/
EclipseLink 2.4.1 Installer Zip (37 MB)
And see example at:
http://theopentutorials.com/tutorials/java/jaxb/jaxb-marshalling-and-unmarshalling-cdata-block-using-eclipselink-moxy/
Good look!.

Bean Autowiring problem

I am starter in mutithreading. I am trying to index my data into solr.For that I was writing the following code
I am getting null pointer exception in the line highlighted
You need to add the following:
<context:annotation-config/>
You need to set the path for autowiring package scan and in your case it will be:
<context:component-scan base-package="a.b.c" />
After it you need to mark the class as candidate for autowiring:
#Component("indexTask")
#Scope("prototype")
IndexTask implements Callable<IndexObject>
{
//ommited
}
Next you can remove indexTask bean configuration from xml file. your package will be created automatically.
Hope it helps.
Autowiring doesn't happen automatically, you need to configure it. See the Spring docs for detail, but essentially you need to add
<context:annotation-config/>

Resources