Ok Maybe I am just really new at this, but I am trying to use this code and it is not updating the custom field value.
Any idea why not? I am guessing its an over sight n my end. Any help is greatly appreciated
def rush = getCustomFieldValue("Rush?")
if (rush=="Yes") {
def cal = new java.util.GregorianCalendar();
cal.setTimeInMillis(customField.setCustomFieldValue("Rush Date", getTime()));
return new java.sql.Timestamp(cal.getTimeInMillis());
}
else {
return null
}
solved
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.customfields.manager.OptionsManager
def componentManager = ComponentManager.instance
def optionsManager = ComponentManager.getComponentInstanceOfType(OptionsManager.class)
def customFieldManager = componentManager.getCustomFieldManager()
def cf = customFieldManager.getCustomFieldObjectByName("Rush?")
def rush = issue.getCustomFieldValue(cf)
def paymentDate = new Date()
if (rush?.value=="Yes"){
if (paymentDate){
def cal = new java.util.GregorianCalendar();
cal.setTimeInMillis(paymentDate.getTime());
cal.add(java.util.Calendar.DAY_OF_MONTH, 0);
return new java.sql.Timestamp(cal.getTimeInMillis());
}
else {
return null
}}
Your snippet, as it stands, fails to me with the following error:
Caught: groovy.lang.MissingMethodException: No signature of method: Custom.getTime() is applicable for argument types: () values: []
That getTime() over there is not being invoked from any object. I guess you want only to setCustomFieldValue in customField, thus, cal.setTimeInMillis()ยน is not needed:
def customField
customField = [
'Rush?':'Yes',
setCustomFieldValue : { field, value -> customField[field] = value }
]
getCustomFieldValue = { customField[it] }
def rush = getCustomFieldValue("Rush?")
def cal = new java.util.GregorianCalendar()
def parseRush = {
if (rush=="Yes") {
customField.setCustomFieldValue("Rush Date", cal.getTime())
return new java.sql.Timestamp(cal.getTimeInMillis())
}
else {
return null
}
}
assert parseRush() == new java.sql.Timestamp(cal.timeInMillis)
assert customField['Rush Date'] == cal.time
Related
I am trying to use reflection to get all the optional fields in a class and their default values (if any). This is my attempt:
fun getOptionalFields(componentType: KClass<out Any>): Map<String, DefaultValueData> {
val cons = componentType.primaryConstructor
val constructorSetup = cons?.parameters
?.filterNot { it.isOptional }
?.associate { it to getValueForNonOptional(it) } ?: error("Something went wrong when choosing default val")
val constructorInst = (cons.callBy(constructorSetup)::class as KClass<Any>)
val conParams = (componentType.primaryConstructor?.parameters ?: emptyList())
.filter { p -> p.isOptional }
.associate { p ->
Pair(p.name ?: "",
DefaultValueData(
p.type,
// the below line crashes
constructorInst.memberProperties.first { m -> m.name == p.name }.get(constructorInst)
)
)
}
return conParams
}
The error: Exception in thread "main" java.lang.IllegalArgumentException: object is not an instance of declaring class
I am a bit puzzled at what get() wants me to pass if not the instance to get the value from?
You are trying to get the value by providing a KClass instead of the actual instance.
This is a working solution based on your method signature and your code above:
data class Test(
val required: String,
val optional: Int = 7
)
val componentType = Test::class
val constructorInst = Test("required") // i skipped constructing the class via constructor
val conParams = (componentType.primaryConstructor?.parameters ?: emptyList())
.filter { p -> p.isOptional }
.associate { p ->
Pair(p.name ?: "",
Pair(
p.type,
componentType.memberProperties.first { m -> m.name == p.name }.get(constructorInst)
)
)
}
println(conParams) // <- OUTPUTS: {optional=(kotlin.Int, 7)}
Why have i removed this code?
val constructorSetup = cons?.parameters
?.filterNot { it.isOptional }
?.associate { it to getValueForNonOptional(it) } ?: error("Something went wrong when choosing default val")
val constructorInst = (cons.callBy(constructorSetup)::class as KClass<Any>)
The resulting object cons.callBy(constructorSetup) is unused because calling ::class on the expression rendered it useless. Additionally it is not required to perform the requested task in your question.
When updating your above code, result will look like
fun getOptionalFields(componentType: KClass<out Any>): Map<String, DefaultValueData> {
val cons = componentType.primaryConstructor
val constructorSetup = cons?.parameters
?.filterNot { it.isOptional }
?.associate { it to getValueForNonOptional(it) } ?: error("Something went wrong when choosing default val")
val constructorInst = cons.callBy(constructorSetup) // <- removed ::class and cast
val conParams = (componentType.primaryConstructor?.parameters ?: emptyList())
.filter { p -> p.isOptional }
.associate { p ->
val value = constructorInst::class.memberProperties.first { m -> m.name == p.name }.get(constructorInst) as KProperty1<out Any, out Any>
Pair(p.name ?: "",
DefaultValueData(
p.type,
value
)
)
}
return conParams
}
I was using a funky way to do it suggested in:
https://stackoverflow.com/a/9072974/4470135
So my code is:
def copyProperties(source, target) {
def (sProps, tProps) = [source, target]*.properties*.keySet()
def commonProps = sProps.intersect(tProps) - ['class', 'metaClass']
commonProps.each { target[it] = source[it] }
}
What I get when I try to call a method that should convert an Entity into a Dto is:
No signature of method: java.util.ArrayList.keySet() is applicable
for argument types: () values: []\nPossible solutions: toSet(),
toSet(), set(int, java.lang.Object), set(int, java.lang.Object),
get(int), get(int)
UPDATE:
My source is a Serializable bean with fields:
private String passengerName;
#NotNull
#Size(min = 5, max = 40)
private String destination;
#NotNull
private String departureDate;
My target is a JPA Entity with the same fields, but with an additional #Id field and a slightly different date representation:
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
ZonedDateTime departureDate
The code is working, however, there are corner cases where it may break.
To fix this replace the property access properties with the method call getProperties(), which might be enough for your case. To cover all cases, you will need to write code for special cases (see bottom)
Working example for the original version
def copyProperties(source, target) {
def (sProps, tProps) = [source, target]*.properties*.keySet()
def commonProps = sProps.intersect(tProps) - ['class', 'metaClass']
commonProps.each { target[it] = source[it] }
}
def a = new Expando()
a.foo = "foo"
a.bar = "bar"
def b = new Expando()
b.baz = "baz"
b.bar = "old"
copyProperties(a, b)
println b
Example causing problems
If the parameters have a property called properties I get the same exception you got (if the value is a List):
def c = new Expando()
c.properties = []
c.bar = "bar"
def d = new Expando()
d.baz = "baz"
d.bar = "old"
copyProperties(c, d)
println d
What works in both cases:
def copyProperties(source, target) {
def (sProps, tProps) = [source, target]*.getProperties()*.keySet()
def commonProps = sProps.intersect(tProps) - ['class', 'metaClass']
commonProps.each { target[it] = source[it] }
}
Not that here I used an explicit call to getProperties rather than just accessing the properties property.
We can still break this
def e = new Object() {
// causes same Exception again
def getProperties() {
return []
}
def bar = "bar"
}
def f = new Expando()
f.baz = "baz"
f.bar = "old"
copyProperties(e, f)
You can fix the last example for e by using the metaClass explicitly
def copyProperties(source, target) {
def (sProps, tProps) = [source, target]*.getMetaClass()*.properties*.name
def commonProps = sProps.intersect(tProps) - ['class', 'metaClass']
commonProps.each { target[it] = source[it] }
}
However, that will fail due to f.
Handle special cases
def getProperties(Expando obj) {
return obj.getProperties().keySet()
}
def getProperties(Object obj) {
return obj.getMetaClass()*.properties*.name
}
def copyProperties(source, target) {
def (sProps, tProps) = [source, target].collect {getProperties(it)}
def commonProps = sProps.intersect(tProps) - ['class', 'metaClass']
commonProps.each { target[it] = source[it] }
}
Here we give objects that need a special treatment what they need ;)
Note that this only works like this for groovy with #CompileDynamic as the decision which getProperties implementation is called will be made at runtime. The alternative is a check with instanceof for all the cases.
User user = User.findById('1')
User copyUser = new User()
InvokerHelper.setProperties(copyUser, user.properties)
I stuck with Unit test in Scala for many days. I cannot inject mock object to Unit test. The ScalatraFlatSpec call to the actual database not my mock variable and i have no idea to do.
This is my API
class Dashboard extends Servlet {
get("/:brand_code") {
val start = System.currentTimeMillis
val brandCode = params.get("brand_code").get
var brandId = 0;
val sqlFind = "SELECT DISTINCT(id) FROM brands WHERE brand_code=?"
val found:List[Map[String, Any]] = ConnectionModel.getExecuteQuery(sqlFind, List(brandCode))
if(found.isEmpty){
halt(404, send("error", s"brand_code [$brandCode] not found."))
}else{
brandId = found(0).getOrElse("id", 0).toString.toInt
send("Yeah55", brandId)
}
}
And this is Servlet
abstract class Servlet extends ScalatraServlet with CorsSupport with JacksonJsonSupport {
protected implicit lazy val jsonFormats: Formats = DefaultFormats.withBigDecimal
protected override def transformResponseBody(body: JValue): JValue = body.underscoreKeys
protected lazy val body = parsedBody.extract[Map[String, Any]]
protected def send(message: String, data: Any = None) = Map("message" -> message, "data" -> data)
options("/*") {
response.setHeader(
"Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers")
)
}
before() {
contentType = formats("json")
}
}
And this is ConnectionModel and ConnectionModelAble
trait ConnectionModelAble {
def getExecuteQuery(sql: String, parameters: List[Any]): List[Map[String, Any]]
}
object ConnectionModel extends ConnectionModelAble{
var connection:Connection = {
val url = "jdbc:mysql://localhost:3306/db"
val username = "root"
val password = ""\
Class.forName("com.mysql.jdbc.Driver")
DriverManager.getConnection(url, username, password)
}
def getExecuteQuery(sql: String, parameters: List[Any]): List[Map[String, Any]]= {
try {
val statement = connection.createStatement()
var preparedStatement: PreparedStatement = connection.prepareStatement(sql);
var formatDate: DateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
// Do some execute
for (i <- 0 until parameters.size) {
parameters(i) match {
case _: Int => preparedStatement.setInt(i + 1, parameters(i).toString.toInt)
case _: Double => preparedStatement.setDouble(i + 1, parameters(i).toString.toDouble)
case _: Date => preparedStatement.setDate(i + 1, new java.sql.Date(formatDate.parse(parameters(i).toString).getTime))
case default => preparedStatement.setString(i + 1, parameters(i).toString)
}
}
val resultSet = preparedStatement.executeQuery()
val metaData: ResultSetMetaData = resultSet.getMetaData();
val columnCount = metaData.getColumnCount();
var ret: List[Map[String, Any]] = List();
while (resultSet.next()) {
var row: Map[String, Any] = Map[String, Any]();
for (i <- 1 to columnCount) {
val columnName = metaData.getColumnName(i);
var obj = resultSet.getObject(i);
row += columnName -> obj
}
ret = ret :+ row
}
ret
}catch {
case e: Exception => {
e.printStackTrace();
List()
}
}
}
And this is my unit test
class DashboardSpec extends ScalatraFlatSpec with MockitoSugar {
addServlet(new Dashboard, "/v1/dashboard/*")
it should "return get dashboard correctly" in {
val brandCode = "APAAA"
val brandId = 157
get("/v1/dashboard/APAAA") {
val connectModel = mock[ConnectionModelAble]
val sqlFind = "SELECT DISTINCT(id) FROM brands WHERE brand_code=?"
Mockito.when(connectModel.getExecuteQuery(sqlFind, List(brandCode))).thenReturn(
List(Map("id" -> 150))
)
assert(status == 200)
println(connectModel.getExecuteQuery(sqlFind, List(brandCode)))
println(body)
}
}
}
I found that body from unit test is not from my mock data, it's from real database. What should i do.
Thank you.
You aren't injecting your mock into the Dashboard, so the Connection you're seeing in getExecuteQuery is the one provided by ConnectionModel.connection. You probably want to use a dependency injection framework or something like the Cake pattern to make sure your Dashboard is referring to your mock instance.
Im trying to iterate over a java util.iterator with Scala but am having trouble with casting the objects to the correct class.
I get the error:
type mismatch; found: java.util.Iterator[?0] where type ?0
required : java.util.iterator[net.percederberg.mibble.MibSymbol]
val iter:util.Iterator[MibSymbol] == mib_obj.getAllSymbols.iterator()
the code looks like following:
import java.io.File
import java.util
import net.percederberg.mibble._
import scala.collection.immutable.HashMap
import scala.collection.JavaConversions._
object Bacon {
def main(args:Array[String]) {
println("hello")
val mib_obj:Mib = loadMib(new File("/Users/tjones24/dev/mibs/DOCS-IF-MIB.my"))
val iter:util.Iterator[MibSymbol] = mib_obj.getAllSymbols.iterator()
while(iter.hasNext()) {
var obj:MibSymbol = iter.next()
println(obj.getName())
}
}
def loadMib(file: File): Mib = {
var loader: MibLoader = new MibLoader()
loader.addDir(file.getParentFile())
return loader.load(file)
}
}
Use an explicit typecast asInstanceOf[Iterator[MibSymbol]]:
def main(args: Array[String]) {
println("hello")
val mib_obj: Mib = loadMib(new File("/Users/tjones24/dev/mibs/DOCS-IF-MIB.my"))
val x = mib_obj.getAllSymbols.iterator()
val iter: util.Iterator[MibSymbol] = x.asInstanceOf[Iterator[MibSymbol]]
while (iter.hasNext()) {
var obj: MibSymbol = iter.next()
println(obj.getName())
}
}
def loadMib(file: File): Mib = {
var loader: MibLoader = new MibLoader()
loader.addDir(file.getParentFile())
return loader.load(file)
}
NOTE: In absence of runtime type information, this may fail.
EDIT1: You can also use a for comprehension:
val mib_obj: Mib = loadMib(new File("/Users/tjones24/dev/mibs/DOCS-IF-MIB.my"))
for ( obj <- mib_obj.getAllSymbols) {
println(obj.asInstanceOf[MibSymbol].getName())
}
import scala.collection.JavaConversions._ does all the magic for you. You only need to ensure that the types are correct.
I have a little problem with my project:
URI
/TimeKeeper/calendar/show
Class
groovy.lang.MissingMethodException
Message
No signature of method: static de.jollyday.util.CalendarUtil.create() is applicable for argument types: (java.util.GregorianCalendar) values:
[java.util.GregorianCalendar[time=1406897280000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Berlin",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=143,lastRule=java.util.SimpleTimeZone[id=Europe/Berlin,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2014,MONTH=7,WEEK_OF_YEAR=31,WEEK_OF_MONTH=0,DAY_OF_MONTH=1,DAY_OF_YEAR=213,DAY_OF_WEEK=6,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=2,HOUR_OF_DAY=14,MINUTE=48,SECOND=0,MILLISECOND=0,ZONE_OFFSET=3600000,DST_OFFSET=3600000]] Possible solutions: create(), create(java.util.Calendar), create(int, de.jollyday.config.Fixed), create(int, int, int), create(int, int, int, org.joda.time.Chronology), grep()
And thats my code where the exception is thrown:
import static java.util.Calendar.*
import de.jollyday.*
import de.jollyday.util.*
class DayReport {
def day
def records
def getHolidayName() {
def m = HolidayManager.getInstance(HolidayCalendar.GERMANY)
def holidays = m.getHolidays(day.get(YEAR), 'nw')
holidays.find {
CalendarUtil.create(day) == it.date
}?.description
}
def isHoliday() {
def m = HolidayManager.getInstance(HolidayCalendar.GERMANY)
def create = CalendarUtil.create(day)
println "DayReport isHoliday: ${create.getClass()}"
m.isHoliday(create, 'nw')
}
...
Can somebody tell me what is wrong?
Thanks :)
def getHolidayName() {
def m = HolidayManager.getInstance(HolidayCalendar.GERMANY)
def holidays = m.getHolidays(day.get(YEAR), 'nw')
holidays.find {
new LocalDate(day.getTime()) == new LocalDate(it.date)
}?.description
}
def isHoliday() {
def m = HolidayManager.getInstance(HolidayCalendar.GERMANY)
def localDate = new LocalDate(day.getTime())
println "localDate: " + localDate
m.isHoliday(localDate, 'nw')
}
That's the solution