nullable environment variables in Symfony - symfony

I know that env variables are string only. Symfony 3.4 supports env variables type casting.
Is there a way to pass null value through int validator?
.env
DATABASE_PORT=
#I also tried DATABASE_PORT=null, DATABASE_PORT=~
parameters.yml
app.connection.port: '%env(int:DATABASE_PORT)%'
#I also tried env(?int, env(int?
I'm getting an error: "Non-numeric env var "DATABASE_PORT" cannot be cast to int." or "Invalid env(?int:DATABASE_PORT) name: only "word" characters are allowed."
In yml there are ~ or null signs used to pass null, e.g:
app.connection.port: ~

Someone asked in the doc:
Is it, or will it be possible to define your own operator? Like
%env(myDecoder:API_PASSWORD)%, which will decrypt the environment
value into something usable.
class MyDecoder implements EnvironmentOperator {
public function resolve(string $value): string {
// magic stuff for decryption
return $value;
}
}
And the answer was:
yes, you just need to create a service that implements
EnvProviderInterface and tag it with container.env_provider.
You could create an operator to accept null as an int

Related

Micronaut custom validation Annotation does not work

I was trying to write a custom annotation to validate a field in a Micronaut project, I came across this section in their documentation Defining Additional Constraints
My understanding was that is completely possible to write my own annotation to validate a field in my POJO but after trying for hours, I can't get my validation to work, it simply does not get invoked, could it be I'm missing something fundamental about the way how Micronaut works?
Annotation
#Retention(RUNTIME)
#Constraint(validatedBy = [])
annotation class FieldValidator(
val message: String = "invalid format ({validatedValue})"
)
Factory
#Factory
class ValidatorFactory {
#Singleton
fun fieldPatternValidator(): ConstraintValidator<FieldValidator, CharSequence> {
return ConstraintValidator { value, annotation, context ->
context.messageTemplate("invalid format ({validatedValue}), should be test")
value == "test"
}
}
}
Filter
#Introspected
data class HelloWorldFilter(
#FieldValidator
val field: String?
)
Controller
#Controller("/hello")
open class HelloController() {
#Get("{?filters*}")
#Produces(MediaType.TEXT_PLAIN)
open fun index(#Valid filters: HelloWorldFilter): String {
return filters.toString()
}
}
I have a small demo on Github, to reproduce
run ./gradlew run
call http://localhost:8080/hello?field=abc that expected behaviour should be bad request since the field is matching the desired value.
Using your demo project, I changed your HelloWorldFilter class to
#Introspected
data class HelloWorldFilter(
#field:FieldValidator
val field: String?
)
Ran it, then:
curl "http://localhost:8080/hello?field=abc"
Output was as you expect:
{"message":"Bad Request","_embedded":{"errors":[{"message":"filters.field: invalid format (abc), should be test"}]},"_links":{"self":{"href":"/hello?field=abc","templated":false}}}
With:
curl "http://localhost:8080/hello?field=test"
Output:
HelloWorldFilter(field=test)

How to call Kotlin companion factory method using callBy()?

I have code accepts a class as a parameter and prepares data to call either the constructor for that class of a companion object factory method if the factory method is present.
All works fine when calling the constructor, but I get the error
java.lang.IllegalArgumentException: No argument provided for a required parameter: instance of fun nz.salect.objjson.JVMTest.StudentWithFactory.Companion.fromJson(kotlin.String, kotlin.Int): nz.salect.objjson.JVMTest.StudentWithFactory
when calling the factory method. The factory method in question:
data class StudentWithFactory(val name: String, val years: Int=0) {
companion object {
fun fromJson(name: String="", age: Int = 0):StudentWithFactory {
return StudentWithFactory(name, age)
}
}
}
has no required parameters, unless there is some hidden parameter. Any ideas?
In fact, I reverted removing the parameters completely from fromJson and directly calling the companion method using ::fromJson.callby(emptyMap()). Same error.
It is clear that companion methods need at least one additional parameter. Perhaps the class? Or the companion object?
How can I specify the needed parameter(s)?
The function building up the callBy() is supplied a class (or finds the class from a supplied class) and json names and values.
var funk:KFunction<*>?=null
val companionFuncs=cls.companionObject?.declaredMemberFunctions
if(companionFuncs?.size ?:0 >0){
companionFuncs?.forEach {
if(it.name == "fromJson") funk=it
}
}
val cons:KFunction<T> = if(funk != null)
funk as KFunction<T>
else
cls.primaryConstructor ?: throw IllegalArgumentException("no primary constructor ${cls.simpleName}")
val valuesMap = cons.parameters.filter{it.name in vals}
.associateBy(
{it},
{generateValue(it)}
)
val data = cons.callBy(valuesMap) //as T
return data
In addition to my short answer, a more technical explanation:
Yes, there actually is a hidden parameter and you can see it (for example), if you take a look at the decompiled (to Java) bytecode:
public final class StudentWithFactory {
// ...
public static final class Companion {
// ...
#NotNull
public static StudentWithFactory fromJson$default(StudentWithFactory.Companion var0, String var1, int var2, int var3, Object var4) {
// ...
return var0.fromJson(var1, var2);
}
// ...
}
}
The first parameter (var0) is actually an instance of the companion object. var1 (name) and var2 (age) are the parameters you declared. var3 is a bitmask for determining if explicit values have been passed or if the default ones should be used*. I honestly don't know what var4 is for. It is unused in the Java code. But the imported part is that you only need to worry about var0, var1 and var2 if you want to invoke the function.
So, in the end the non-static version of fromJson* is actually invoked on the instance of the companion object:
var0.fromJson(var1, var2)
*left code out for simplicity
You can use the parameters property to determine how much parameters you have to pass to the function/constructor.
If you call
val paramsConstr = StudentWithFactory::class.primaryConstructor?.parameters
paramsConstr will be of size two as expected, but if you call
val paramsFunc = ::fromJson.parameters
paramsFunc will be of size three. The first element corresponds to the instance of the companion object. So, thats the list of parameters you need to provide.
You can invoke the fromJson like this:
// not using any default parameters
::fromJson.callBy(mapOf(
paramsFunc[0] to StudentWithFactory::class.companionObjectInstance,
paramsFunc[1] to "Hello",
paramsFunc[2] to 30
))
// using only the default parameter for "name"
::fromJson.callBy(mapOf(
paramsFunc[0] to StudentWithFactory::class.companionObjectInstance,
paramsFunc[2] to 30
))

How to define an index using the new bolt compiler for Firebase

I'm using the new bolt compiler (introduced here: https://www.firebase.com/blog/2015-11-09-introducing-the-bolt-compiler.html)
I have the need to define an index on the owner field of my type Event:
type Event {
description : String | Null,
name : String,
color : Number,
owner : String,
shared : Boolean
index() = "owner";
}
When I try to compile this code, I get the following output:
bolt: Generating rules.json...
bolt:1:1: Unsupported method name in type statement: 'index' (allowed: 'validate', 'read', 'write')
Please help: how should I define indexes? I guess I need to define them within a path statement?
The documentation for the bolt compiler does not contain much on defining indexes yet: https://github.com/firebase/bolt/blob/master/docs/language.md
Just found the answer:
path /users/$uid/events {
index() = "owner";
}
Combining the type info with the index:
path /events is Event[] {
index() = "owner";
}

why does the compiler complain about missing ctor of WebSocketHandler?

I'm trying to use websocket in my project.
to do so, I installed the package Microsoft Asp.Net SignalR, which consists of WebSocketHandler abstract class.
i defined a class inheriting WebSocketHandler, but then the compiler complains:
'Microsoft.AspNet.SignalR.WebSockets.WebSocketHandler' does not contain a constructor that takes 0 arguments'.
It seems wierd to me, because the definitioin of WebSocketHandler ctor gets a nullable value, which means the ctor could get no parameter,
the definition looks like this:
protected WebSocketHandler(int? maxIncomingMessageSize);
can anybody tell me what the problem is?
thanks.
It seems wierd to me, because the definitioin of WebSocketHandler ctor gets a nullable value, which means the ctor could get no parameter
No, it doesn't. There's a big difference between receiving a null value for a nullable type, and not receiving a value at all.
If the parameter were optional, that would be a different matter - but it's not. You have to supply an argument convertible to int? in the call. If you want to provide the null value for int?, do so:
var handler = new WebSocketHandler(null);
Or if you want to avoid accidentally using any other single-parameter constructor definitions which may be applicable with a null literal as the argument, you could use:
var handler = new WebSocketHandler((int?) null);
Or:
var handler = new WebSocketHandler(default(int?));
protected member is accessible by derived class instances and there's nothing special about it. Nothing special in the class itself, either # WebSocketHandler.cs.
It just mens you need to pass in a nullable type, it does not mean it can't get any arguments.
int? maxIncomingMessageSize = 0;
var socket = new WebSocketHandler(maxIncomingMessageSize);
In your derived class you could/should define a "constructor that takes 0 arguments".
public class MyHandler : WebSocketHandler
{
// not mandatory
public MyHandler()
:this(null)
{}
// mandatory
public MyHandler(int? maxIncomingMessageSize)
:base(maxIncomingMessageSize)
{}
}

How to get name of method parameter/argument in groovy?

I have groovy script that has a function with 2 arguments, one of which is a hashmap. I want to check the name of a hashmap variable contains a substring or not, inside a function. How do i do it?
def myfunc(String var, HashMap var2)
{
// need a routine to retrive the name of the variable var2
}
It's well explained here :
Getting the name of a method parameter
To access groovy script's method follow syntax :
metaClass.methods
Sounds like you want the --parameters (alias -pa) compiler argument.
Generates metadata for reflection on method parameter names on JDK 8 and above. Defaults to false.
Usage: groovy --parameters Person.groovy
Also available for groovyc, groovyConsole, groovysh and groovy ant tasks. Check out the PR some awesome person contributed...
e.g.
class HelloWorld {
static void speak(String firstName) {
println "Hello $firstName"
}
}
Student.methods.each {
if (it.name === 'speak') println it.parameters
}
// groovy HelloWorld.groovy => "[java.lang.String arg0]"
// groovy -pa HelloWorld.groovy => "[java.lang.String firstName]"

Resources