I've been using Groovy for a few years, but not in the last few months, so this could just be a newbie question. I'm trying to parse a log file, but when I try to do this:
myFile.eachLine { line ->
/* 2014 Jul 30 08:55:42:645 GMT -4 BW.TMSJobService-TMSJobService-1
* User [BW-User] - Job-2584 [Process/Common/LogAuditInfo.process/WriteToLog]: */
/* 1234567890123456789012345678901 */
/* 0 1 2 3 */
LogItem logItem = new LogItem()
// get the time stamp
String timestamp = line.substring(0, 31)
SimpleDateFormat sdf = new SimpleDateFormat('yyyy MMM dd HH:mm:ss:S')
logItem.date = sdf.parse(timestamp)
}
I get this exception:
Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: java.text.SimpleDateFormat.parse() is applicable for argument types: (java.lang.String, ce.readscript.TmsLogReader$_read_closure1_closure3) values: [2014 Jul 30 08:34:47:079 GMT -4, ce.readscript.TmsLogReader$_read_closure1_closure3#14235ed5]
Possible solutions: parse(java.lang.String), parse(java.lang.String, java.text.ParsePosition), parse(java.lang.String, java.text.ParsePosition), wait(), clone(), clone()
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:46)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
It's always the last line in the closure. If I add code after the 'parse', then it bombs on this code. Even a "079".toLong() call gets a error.
I see some similar errors in stack overflow, but nothing that solves my problem.
It is trying to invoke SimpleDateFormat::parse(String, Closure) which doesn't exist. There seems to be a typo somewhere. It is working fine under groovy 2.1.8 and 2.3.4. You can try to make it a bit more groovy, to check whether it has some typing error not in your example:
new File("log.log").eachLine { line ->
def item = new LogItem()
def timestamp = line[0..30]
item.date = Date.parse('yyyy MMM dd HH:mm:ss:S', timestamp)
}
I used the time honored technique of deleting the file and starting over. I haven't encountered the issue again.
Related
I am having a hard time using an environment variable with a space in a properties file read by WildFly (24) in Linux using Oracle 19 in RDS. One like:
SELECT 1 FROM DUAL
The issue is that wildfly won't even parse the file if the spaces are in there with the normal quoting methods.
I have it setup so that variable is in a file called datasource.properties that gets read from standalone.conf where this variable sits:
JAVA_OPTS="$JAVA_OPTS -DDATABASE_CONNECTION_CHECK=${DATABASE_CONNECTION_CHECK}"
It's read in with the following in standalone.conf:
set -a
. /opt/wildfly_config/datasource.properties
set +a
That in turn gets populated in standalone.xml with:
<connection-url>${env.DATABASE_JDBC_URL}</connection-url>
I try putting it in quotes and oddly enough it doesn’t start at all. Standalone.sh is no longer able to parse it:
Error: Could not find or load main class 1 Caused by: java.lang.ClassNotFoundException: 1
I have tried many things such as:
DATABASE_CONNECTION_CHECK="SELECT{ }1{ }FROM{ }DUAL"
DATABASE_CONNECTION_CHECK="'SELECT 1 FROM DUAL'"
DATABASE_CONNECTION_CHECK='SELECT 1 FROM DUAL'
DATABASE_CONNECTION_CHECK="SELECT+1+FROM+DUAL"
DATABASE_CONNECTION_CHECK="SELECT\ 1\ FROM\ DUAL"
DATABASE_CONNECTION_CHECK="\"SELECT 1 FROM DUAL\""
DATABASE_CONNECTION_CHECK="\"'SELECT 1 FROM DUAL'\""
DATABASE_CONNECTION_CHECK="SELECT%201%20FROM%20DUAL"
DATABASE_CONNECTION_CHECK="SELECT\{ }1\{ }FROM\{ }DUAL"
DATABASE_CONNECTION_CHECK='SELECT{ }1{ }FROM{ }DUAL'
DATABASE_CONNECTION_CHECK="'SELECT{ }1{ }FROM{ }DUAL'"
DATABASE_CONNECTION_CHECK="''SELECT{ }1{ }FROM{ }DUAL''"
DATABASE_CONNECTION_CHECK="SELECT%1%FROM%DUAL"
(I realize some of these don't make sense but I was looking for anything different.)
Startup looks good in the log output this with some of these, but then java doesn’t like it, for some reason it sees the escape usage:
Caused by: Error : 936, Position : 9, Sql = SELECT+1+FROM+DUAL, OriginalSql = SELECT+1+FROM+DUAL, Error Msg = ORA-00936: missing expression
or
Caused by: Error : 911, Position : 6, Sql = SELECT%1%FROM%DUAL, OriginalSql = SELECT%1%FROM%DUAL, Error Msg = ORA-00911: invalid character
or
WARN [org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory] (ServerService Thread Pool -- 46) IJ030027: Destroying connection that is not valid, due to the following exception: oracle.jdbc.driver.T4CConnection#2c1456f8: java.sql.SQLException: Non supported SQL92 token at position: 7
This last one is the only one that really netted anything different. I got that with:
DATABASE_CONNECTION_CHECK="SELECT{}1{}FROM{}DUAL"
I can use sed to change the value in the standalone.xml, but all of the other properties I am doing work fine with the exception of this one. I had a hard time with a semicolon in the jdbc string with MSSQL and putting the semicolon in braces like "{;}" fixed that. This DB apparently does not follow the same syntax.
Is there an encoding type that will help this with Oracle and keeps wildfly happy?
EDIT: More tests:
DATABASE_CONNECTION_CHECK=\"SELECT' '1' 'FROM' 'DUAL\"
gets
Caused by: Error : 900, Position : 0, Sql = "SELECT 1 FROM DUAL", OriginalSql = "SELECT 1 FROM DUAL", Error Msg = ORA-00900: invalid SQL statement'
(doesn't seem to like the quotes)
But without the escaping of the quotes I get:
Caused by: Error : 923, Position : 9, Sql = SELECT' '1' 'FROM' 'DUAL, OriginalSql = SELECT' '1' 'FROM' 'DUAL, Error Msg = ORA-00923: FROM keyword not found where expected
A better solution was to change the sourcing of the file from:
set +a
. /opt/PrimeKey/wildfly_config/datasource.properties
set -a
to
. /opt/PrimeKey/wildfly_config/datasource.properties
and make it so all the variables brought in were variables and not properties:
export DATABASE_CONNECTION_CHECK="SELECT 1 FROM DUAL"
I want to to set Property value in SOAPUI with current time + 5 minutes
i tried this:
import groovy.time.*
import org.codehaus.groovy.runtime.TimeCategory
import groovy.time.TimeCategory
import java.text.SimpleDateFormat
currentDate = new Date()
use( TimeCategory ) {
after30Mins = date + 30.minutes
}
testRunner.testCase.testSuite.project.setPropertyValue( "SendHour",after30Mins)
log.info (after30Mins)
I got this error:
groovy.lang.MissingMethodException: No signature of method: com.eviware.soapui.impl.wsdl.WsdlProject.setPropertyValue() is applicable for argument types: (java.lang.String, java.util.Date) values: [SendHour, Sun Jun 07 19:37:52 EDT 2015] Possible solutions: setPropertyValue(java.lang.String, java.lang.String), getPropertyValue(java.lang.String) error at line: 10
Any help please, Thank you
As the error message says, the method setPropertyValue takes 2 parameters, both od them String. So the solution is to cast the after3OMins variable to String. In Groovy, Date implements the format method that makes casting to String really easy. In our case it could look like
testRunner.testCase.testSuite.project.setPropertyValue( "SendHour",
after30Mins.format("yyyy-MM-dd'T'HH:mm:ssZ"))
I have one test step which contains two assertion.
Not SOAP Fault
Contains. The Condition is that response should contain "Message Sent Successfully"
Now I have one groovy script, from where I am executing this test step. Using this groovy script I need to print assertion name, Value and Status. Below is the code I have written:
testStepSrc = testCase.getTestStepByName(testName)
Assertioncounter = testStepSrc.getAssertionList().size()
for (AssertionCount in 0..Assertioncounter-1)
{
log.info("Assertion :" + testStepSrc.getAssertionAt(AssertionCount).getName() + " :: " + testStepSrc.getAssertionAt(AssertionCount).getStatus())
error = testStepSrc.getAssertionAt(AssertionCount).getErrors()
if (error != null)
{
log.error(error[0].getMessage())
}
}
but in output it is displaying like:
Wed Sep 04 17:21:11 IST 2013:INFO:Assertion :Not SOAP Fault :: VALID
Wed Sep 04 17:21:11 IST 2013:INFO:Assertion :Contains :: VALID
As you can see, I am able to print assertion name and status but not the value of 'Contains' assertion. Please help me how to get the value of a particular assertion.
Thanks in advance.
So here is some things for you to read
http://www.soapui.org/forum/viewtopic.php?t=359
http://whathaveyoutried.com
and what i tried
def assertionsList = testRunner.getTestCase().getTestStepByName("Test Step Name").getAssertionList()
for( e in assertionsList){
log.info e.getToken() //gives the value of the content to search for
log.info e.DESCRIPTION
log.info e.ID
log.info e.LABEL
log.info e.toString()
}
This gives the following output
Wed Sep 04 15:12:19 ADT 2013:INFO:Abhishek //the contains assertion was checking for the word "Abhishek" in the response of my test step where the assertion was applied.
Wed Sep 04 15:12:19 ADT 2013:INFO:Searches for the existence of a string token in the property value, supports regular expressions. Applicable to any property.
Wed Sep 04 15:12:19 ADT 2013:INFO:Simple Contains
Wed Sep 04 15:12:19 ADT 2013:INFO:Contains
Wed Sep 04 15:12:19 ADT 2013:INFO:com.eviware.soapui.impl.wsdl.teststeps.assertions.basic.SimpleContainsAssertion#c4115f0
Abhishek's response did contain you answer I believe but just not in the format you were looking for.
I was looking for the same info for custom reporting and after digging through The SoapUI forms I stumbled upon this.
The piece of code that I believe you are looking for is:
log.info e.getToken()
however this is an example of how to retrieve it only when an error occurs but you can get it in a valid scenario using something similar to:
def iAssertionName = assertionNameList[j]
def iAssertionStatus = testStep.getAssertionAt(j).getStatus().toString()
def tstep = testStep.getName()
def gStatus = testStep.getAssertionAt(j).status
def expect = testStep.getAssertionAt(j).getToken()
log.info "Expected Content: " + expect
This is a subset of my code but produces the log message:
Fri Sep 20 11:04:09 CDT 2013:INFO:Expected Content: success
My SoapUI script assertion was checking to see if my response contained the string "success".
Thanks Abhishek for your response!
I have a quartz cron trigger that looks like so:
<bean id="batchProcessCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="batchProcessJobDetail" />
<property name="cronExpression" value="0 30 2 * * ?" />
</bean>
How should I solve this, if I have several configurations that happen within the 2-3am period? Is there an accepted best practice?
Relevant link: http://www.quartz-scheduler.org/docs/faq.html#FAQ-daylightSavings
Basically it says "Deal with it." But my question is how!
I solved it using a separate trigger that only fires (an hour early) on the beginning date of DST for the configurations that happen between 2am and 3am Eastern.
Seems kludgey, but it works...
We are using the following solution. For this you will also need the joda time library.
public class MyCronExpression extends CronExpression
{
CronExpression _orgCronExpression;
public MyCronExpression(String cronExpression) throws ParseException
{
super(cronExpression);
setTimeZone(TimeZone.getTimeZone("UTC"));
_orgCronExpression = new CronExpression(cronExpression);
}
#Override
public Date getTimeAfter(Date date)
{
Date date1 = super.getTimeAfter(new Date(date.getTime()-date.getTimezoneOffset()*60*1000));
if (TimeZone.getDefault().inDaylightTime( date1 ) && !TimeZone.getDefault().inDaylightTime( date ))
{
DateTimeZone dtz = DateTimeZone.getDefault();
Date dstEnd = new Date(dtz.nextTransition(date.getTime()));
int dstEndHour = dstEnd.getHours();
int dstDuration = (dtz.getOffset(date1.getTime()) - dtz.getStandardOffset(date1.getTime()))/(60*60*1000);
int hour = date1.getHours()+date1.getTimezoneOffset()/60;
if (hour < dstEndHour && hour >= dstEndHour-dstDuration)
return dstEnd;
else
return _orgCronExpression.getTimeAfter(date);
}
else
return _orgCronExpression.getTimeAfter(date);
}
}
The class is used as follows:
CronTriggerImpl trigger = new CronTriggerImpl();
trigger.setCronExpression(new MyCronExpression("0 15 2 * * ?"));
Here some sample trigger times:
Tue Mar 25 02:15:00 CET 2014
Wed Mar 26 02:15:00 CET 2014
Thu Mar 27 02:15:00 CET 2014
Fri Mar 28 02:15:00 CET 2014
Sat Mar 29 02:15:00 CET 2014
**Sun Mar 30 03:00:00 CEST 2014**
Mon Mar 31 02:15:00 CEST 2014
Tue Apr 01 02:15:00 CEST 2014
Wed Apr 02 02:15:00 CEST 2014
Please post if you find any bugs/issues with this solution.
I took Ron's very interesting answer and improved the getTimeAfter Method, In order to adjust it to server GMT running and possible differences when scheduling 'Once a year' cron expressions.
#Override
public Date getTimeAfter(Date date) {
Date nextDate = super.getTimeAfter(date);
if(nextDate == null){
return null;
}
DateTime date1 = new DateTime(nextDate);
if (getTimeZone().inDaylightTime(date1.toDate()) && !getTimeZone().inDaylightTime(date)) {
DateTimeZone dtz = DateTimeZone.forTimeZone(getTimeZone());
DateTime dstEndDateTime = new DateTime(new Date(dtz.nextTransition(date.getTime())));
int dstEndHour = dstEndDateTime.getHourOfDay();
int dstDuration = (dtz.getOffset(date1.getMillis()) - dtz.getStandardOffset(date1.getMillis())) / (60 * 60 * 1000);
int hour = date1.getHourOfDay();
// Verifies if the scheduled hour is within a phantom hour (dissapears upon DST change)
if (hour < dstEndHour && hour >= dstEndHour-dstDuration){
// Verify if the date is a skip, otherwise it is a date in the future (like threads that run once a year)
if(dstEndDateTime.getDayOfYear() == date1.minusDays(1).getDayOfYear()){
return dstEndDateTime.toDate();
}else{
return nextDate;
}
}else{
return nextDate;
}
} else{
return nextDate;
}
}
Please note my server runs in GMT mode, therefore I do not use some of the offset conversions present in Ron's answer.
Also I discovered a Quartz bug, in which if you use the following configuration, it will fail because it is not capable of processing the cron expression correctly:
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
String cron = "0 15 2 8 3 ? 2015";
FailsafeCronExpression cronExpression = new FailsafeCronExpression(cron);
cronExpression.setTimeZone(DateTimeZone.forID("America/Vancouver"));
DateTime nextDate = new DateTime(cronExpression.getTimeAfter(sdf.parse("12/11/2014 10:15:00")));
This actually seems to happen because DST change takes place during 9th of March 2am for Vancouver and seems the Quartz internal implementation of the super.getTimeAfter(date) method will always send null.
I hope this information is useful.
I'm aware this question is quite old, but it still seems valid. I believe i've found a way to solve this problem, i'l leave it here in case someone else sumbles upon it and finds it handy
With spring 5.3 comes improved scheduling, rewritten using java.time API. It also supports quartz-specific extensions to cron expressions.
Example computation code:
public Instant calculateNextExecution(String cronExpression, Instant lastExecutionInstant, ZoneId executionZoneId) {
LocalDateTime lastExecutionDateTimeInExecutionZone lastExecutionInstant.atZone(executionZoneId)
.toLocalDateTime();
LocalDateTime nextExecutionDateInExecutionZone = CronExpression.parse(cronExpression).next(lastExecutionDateTimeInExecutionZone);
// skipped checking and handling nonexistant next execution
ZoneOffsetTransition transition = executionZoneId.getRules().getTransition(nextExecutionDateInExecutionZone);
if (transition == null) {
// next execution didn't occur during time transition
return nextExecutionDateInExecutionZone.atZone(executionZoneId)
.toInstant();
} else {
// next execution occured during time transition, one might check if transition was a gap or overlap and do sth with it
return doSthWithIt(transition, nextExecutionDateInExecutionZone);
}
}
Relevant spring class is org.springframework.scheduling.support.CronExpression.
Detailed description https://spring.io/blog/2020/11/10/new-in-spring-5-3-improved-cron-expressions
#update: Spring scheduler doesn't support years in cron expressions :( so it might not work in you scenario
When I analyzed a crush dump file, I often got such errors:
0:025> kP
Child-SP RetAddr Call Site
00000000`05a4fc78 00000000`77548638 ntdll!DbgBreakPoint(void) [d:\w7rtm\minkernel\ntos\rtl\amd64\debugstb.asm # 51]
00000000`05a4fc80 00000000`774b39cb ntdll!DbgUiRemoteBreakin(
void * Context = 0x00000000`00000000)+0x38 [d:\w7rtm\minkernel\ntdll\dlluistb.c # 310]
00000000`05a4fcb0 00000000`00000000 ntdll!RtlUserThreadStart(
<function> * StartAddress = 0x00000000`00000000,
void * Argument = 0x00000000`00000000)+0x25 [d:\w7rtm\minkernel\ntos\rtl\rtlexec.c # 3179]
It seems that the process crushed when creating a thread. So, I want to find who or which thread created the current thread. How can I get it?
You can look at the other threads in the process with ~*k to see if there's anything interesting. Other than that, this info simply isn't there in the dump.
-scott