I try to pass parameters using quartz(1.6) api in ServletA
JobDataMap map = new JobDataMap();
map.put("date", "20151101");
scheduler = new StdSchedulerFactory().getScheduler();
scheduler.triggerJob(jobName, groupName, map);
When I trigger JobA, it work.
But I can't get parameter in JobA from folloing code.
map is null.
JobDataMap map = jobExecutionContext.getJobDetail().getJobDataMap();
String date = (String) map.get("date");
Do I miss something important?? Thanks for help.
Parameter maps can be passed to the execution from the job or/and the trigger. In your solution you explicitely try to get the job's datamap (at ctx.getJobDetail().getJobDataMap()) , which is null because you set your parameters via the trigger.
You can use the getMergedJobDataMap of JobExecutionContext to get a parameter map merged from both:
JobDataMap map = jobExecutionContext.getMergedJobDataMap();
String date = (String) map.get("date");
Related
I have a DynamoDb table with a GSI over two keys - string field 'id' (partition key) and number field 'count' (sort key).
I'm trying to work out how to run a query (not scan) via a Spring Java application using the DynamoDbEnhancedClient in the SDK on this table for the key condition expression:
#id = :idValue and #count between :minCount and :maxCount
I can build two separate QueryConditional objects for each part of this compound expression, for example:
var partitionKeyConditional = QueryConditional.keyEqualTo(Key.builder()
.partitionValue("myIdValue")
.build());
var sortKeyConditional = QueryConditional.sortBetween(Key.builder()
.sortValue(0)
.build(), Key.builder()
.sortValue(100)
.build());
But I don't know how to combine these in the actual query request:
dynamoDbEnhancedClient.table(myTableName, TableSchema.fromBean(TableObject.class))
.query(QueryEnhancedRequest.builder()
.queryConditional(SomeJoinFunction??(partitionKeyConditional, sortKeyConditional))
.build())
.items();
I can see I could use a filterExpression, but I assume this would occur after the key conditions have been applied in the query to select results, so the advantage of the sort key definition is essentially lost. It most closely resembles the functionality that I want however:
var expressionAttributeNames = new HashMap<String, String>() {{
put("#id", ID_PROPERTY_NAME);
put("#count", COUNT_PROPERTY_NAME);
}};
var expressionAttributeValues = new HashMap<String, AttributeValue>() {{
put(":idValue", AttributeValue.builder().s("myId").build());
put(":minCount", AttributeValue.builder().n("0").build());
put(":maxCount", AttributeValue.builder().n("100").build());
}};
var queryExpression = Expression.builder()
.expressionNames(expressionAttributeNames)
.expressionValues(expressionAttributeValues)
.expression("#id = :idValue and #count between :minCount and :maxCount")
.build();
I am probably missing something obvious, any suggestions?
The Key Builder used by the QueryConditionals can take both a partitionKey and sortKey value to build its expression. So when you build your QueryConditional.sortBetween object, you can define the matching partitionKey there:
var partitionKeyValue = "myIdValue"
var sortKeyConditional = QueryConditional.sortBetween(Key.builder()
.partitionValue(partitionKeyValue)
.sortValue(0)
.build(), Key.builder()
.partitionValue(partitionKeyValue)
.sortValue(100)
.build());
i have created job with like creating with one jobName and different keys(see JobDataMap)
CronTriggerImpl trigger = new CronTriggerImpl();
JobDetailImpl jobDetail = null;
trigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING);
trigger.setName(getUniqueJobId());
trigger.setCronExpression(cronExpression);
trigger.setTimeZone(timeZone);
JobDataMap dataMap = new JobDataMap();
dataMap.put("jobName", "job");
dataMap.put("id", "key");
trigger.setJobDataMap(jobDataMap);
jobDetail = new JobDetailImpl();
jobDetail.setName(getUniqueJobId());
jobDetail.setJobDataMap(jobDataMap);
jobDetail.setJobClass(JobLauncherDetails.class);
scheduler.scheduleJob(jobDetail, trigger);
it is working properly but i want to delete the specific trigger how can i delete
i had seen fee source but those are not matching. please help me out
**Updated : **
i want to delete like
schedule.deleteJob(JobKey) what will be the job key as per my schedule configuration
or should i use schedule.unScheduler()
org.quartz.Scheduler#unscheduleJob accepts the trigger key as parameter. Hence, you can remove the trigger specified, not the job.
public static boolean removeJob(String jobName, String jobGroup) throws SchedulerException {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
if (scheduler.checkExists(triggerKey)) {
scheduler.unscheduleJob(triggerKey); // trigger + job
}
logger.info(">>>>>>>>>>> removeJob success, triggerKey:{}", triggerKey);
return true;
}
Hope that helps.
UPDATE:
We don't know actually your functional need. But, you can create Trigger in cleaner way and bind it to a given Job:
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0/2 8-17 * * ?"))
.forJob("myJob", "group1") // Binding the Trigger to the Job
.build();
I see you are using JobDataMap in your Trigger. This is useful for passing parameters to a Job that are specific to the executions of the trigger. Do you need really that?
Useful link: https://www.baeldung.com/quartz
I'm using DynamoDB, I have table called "cache" with only one field that is String - "apiToken", how can I get this String from DB when I have only that one field? Is this even possible?
private String getAuthToken() {
// TODO: Replace with cache fetched from DB instead of refreshApiToken method
Cache cache = new Cache();
cache.setApiToken(this.refreshApiToken());
return cache.getApiToken();
}
If you only store one item in DynamoDB, I suggest to get rid of DynamoDB at all and use AWS Systems Manager Parameter Store instead.
If you want to stick to DynamoDB you can make a ScanRequest to get the first item.
ScanRequest scanRequest = new ScanRequest()
.withTableName("cache")
.withLimit(1);
ScanResult result = client.scan(scanRequest);
// handle result.getItems() ...
I'm trying to get the objectId of an object that I have updated - this is my java code using the java driver:
Query query = new Query();
query.addCriteria(Criteria.where("color").is("pink"));
Update update = new Update();
update.set("name", name);
WriteResult writeResult = mongoTemplate.updateFirst(query, update, Colors.class);
Log.e("object id", writeResult.getUpsertedId().toString());
The log message returns null. I'm using a mongo server 3.0 on mongolab as I'm on the free tier so it shouldn't return null. My mongo shell is also:
MongoDB shell version: 3.0.7
Is there an easy way to return the object ID for the doc that I have just updated? What is the point of the method getUpsertedId() if I cannot return the upsertedId?
To do what I want, I currently have to issue two queries which is highly cumbersome:
//1st query - updating the object first
Query query = new Query();
query.addCriteria(Criteria.where("color").is("pink"));
Update update = new Update();
update.set("name", name);
WriteResult writeResult = mongoTemplate.updateFirst(query, update, Colors.class);
//2nd query - find the object so that I can get its objectid
Query queryColor = new Query();
queryColor.addCriteria(Criteria.where("color").is("pink"));
queryColor.addCriteria(Criteria.where("name").is(name));
Color color = mongoTemplate.findOne(queryColor, Color.class);
Log.e("ColorId", color.getId());
As per David's answer, I even tried his suggestion to rather use upsert on the template, so I changed the code to the below and it still does not work:
Query query = new Query();
query.addCriteria(Criteria.where("color").is("pink"));
Update update = new Update();
update.set("name", name);
WriteResult writeResult = mongoTemplate.upsert(query, update, Colors.class);
Log.e("object id", writeResult.getUpsertedId().toString());
Simon, I think its possible to achieve in one query. What you need is a different method called findAndModify().
In java driver for mongoDB, it has a method called findOneAndUpdate(filter, update, options).
This method returns the document that was updated. Depending on the options you specified for the method, this will either be the document as it was before the update or as it is after the update. If no documents matched the query filter, then null will be returned. Its not required to pass options, in that case it will return the document that was updated before update operation was applied.
A quick look at the mongoTemplate java driver docs here: http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/FindAndModifyOptions.html tells me that you can use the method call:
public <T> T findAndModify(Query query,
Update update,
FindAndModifyOptions options,
Class<T> entityClass)
You can also change the FindAndModifyOptions class to take on an 'upsert' if the item was not found in the query.If it is found, the object will just be modified.
Upsert only applies if both
The update options had upsert on
A new document was actually created.
Your query neither has upsert enabled, nor creates a new document. Therefore it makes perfect sense that the getUpsertedId() returns null here.
Unfortunately it is not possible to get what you want in a single call with the current API; you need to split it into two calls. This is further indicated by the Mongo shell API for WriteResults:
The _id of the document inserted by an upsert. Returned only if an
upsert results in an insert.
This is an example to do this with findOneAndUpdate(filter,update,options) in Scala:
val findOneAndUpdateOptions = new FindOneAndUpdateOptions
findOneAndUpdateOptions.returnDocument(ReturnDocument.AFTER)
val filter = Document.parse("{\"idContrato\":\"12345\"}")
val update = Document.parse("{ $set: {\"descripcion\": \"New Description\" } }")
val response = collection.findOneAndUpdate(filter,update,findOneAndUpdateOptions)
println(response)
I have a Quartz job written in Java which runs fine if I have the Quartz JobDetail line set as follows:
JobDetail jd = new JobDetail("FeedMinersJob", scheduler.DEFAULT_GROUP, FeedMinersScheduler.class);
But I would like to dynamically load the class because the job details are stored in a database table. So I want something like this:
JobDetail jd = new JobDetail(sj.getJobName(), scheduler.DEFAULT_GROUP, sj.getJobClassFile());
Where sj is a scheduled job object and method sj.getJobClassFile() returns the name of the class defined in sj instead of having the class name hardcoded.
I've tried permutations of the Java Class.forName method but without success.
I ran into the same issue.
It does not output anything, and does not throw an error either.
This is because your job class doesn't have an empty constructor. So even though the code is correct, it has no mechanism to create the job object.
If you add an empty constructor to your Job class, itwill work.
As I understand it, you code should like this:
Class<?> jobClass = Class.forName(sj.getJobClassFile());
JobDetail jd = new JobDetail(sj.getJobName(), scheduler.DEFAULT_GROUP, jobClass);
Can you please post the code snippets which didn't work?
Try this
try {
Class<?> jobClass = Class.forName(sj.getJobClassFile());
JobDetail jd = new JobDetail(sj.getJobName(), scheduler.DEFAULT_GROUP, jobClass);
} catch (ClassNotFoundException e) {
// put here some error handling
}
And if it doesn't work please give more details about the problem - compilation error, exception in runtime or some other problem.
I have this, maybe it will be usefull to you: (getClassName() returns a string)
Class<?> jobClass = Class.forName(t_job.getClassName());
if (Job.class.isAssignableFrom(jobClass)) {
// create a job detail that is not volatile and is durable (is persistent and exists without trigger)
JobDetail job = new JobDetail(t_job.getName(), t_job.getGroupName(), jobClass, false, true, true);
job.setDescription(t_job.getDescription());
}