How to exclude mutations from Query root node with spqr? - kotlin

I use io.leangen.graphql.spqr library version 0.9.6 and I need to exclude mutations from Query root node into the Doc.
My GraphQLController.kt looks this way:
#RestController
class GraphQLController {
private var graphQL: GraphQL? = null
#Autowired
fun GraphQLController(bookGraph: BookGraph) {
val schema = GraphQLSchemaGenerator()
.withResolverBuilders(
AnnotatedResolverBuilder(),
PublicResolverBuilder("com.example.graphql.spqr"))
.withOperationsFromSingleton(bookGraph)
.withValueMapperFactory(JacksonValueMapperFactory())
.generate()
graphQL = GraphQL.newGraphQL(schema)
.build()
}
#PostMapping(value = ["/graphql"], consumes = [MediaType.APPLICATION_JSON_UTF8_VALUE], produces = [MediaType.APPLICATION_JSON_UTF8_VALUE])
#ResponseBody
fun execute(#RequestBody request: Map<String?, Any?>): ExecutionResult? {
return graphQL!!.execute(ExecutionInput.newExecutionInput()
.query(request["query"] as String?)
.variables(request["variables"] as Map<String, Object>?)
.operationName(request["operationName"] as String?)
.build())
and my BookGraph.kt looks this way:
#Component
class BookGraph {
#Autowired
private lateinit var bookService: BookService
#GraphQLQuery(name = "books")
fun books() : List<Book> {
return bookService.findAll()
}
#GraphQLMutation(name = "createBook")
fun createBook(#GraphQLInputField(name = "name") name: String) : Book {
return bookService.findAll()
}
}
How can I do it?
I searched for possible solutions both in StackOverflow and SPQR issues but cannot find a solution.
Example of Query root node below, I want to exclude createBook:
While I want Mutation root node to remain untouched:

It's bug. You're using a very old version of SPQR (Feb. 2018). This has been fixed a long long time ago. Please try to follow the releases as much as possible, as lots of things are getting fixed and improved.
It is possible to work around the bug by customizing the ResolverBuilders, but I wouldn't recommend going that route.
The Spring Starter (if even relevant to you) is currently lagging behind (not yet on the latest SPQR version) but I'm actively working on the new release. Should be out very soon.
Btw, your setup has a lot of redundancy. Can be simplified to:
val schema = GraphQLSchemaGenerator()
.withOperationsFromSingleton(bookGraph)
//replace with your own root package(s)
.withBasePackages("com.example.graphql.spqr")
.generate()

Related

Kotlin Cancels getParceableExtra call when passing data class using Intent

Trying to pass a data class User from one Activity to another using Intent.
My putExtra looks like this using my observe fun:
val intent = Intent(this, MainActivity::class.java)
intent.putExtra("userData",userData)
startActivity(intent)
My get routine looks like this:
userData = intent.getParcelableExtra<User>("userData") as User
or
userData = intent.getParcelableExtra("userData")
My problem is that Android Studio strikes out the function. My User data class is marked #Parcelize. It all ends up getParcelableExtra.
I've add to my gradle build:
id 'kotlin-parcelize'
I've read several posts about Parcelable being more modern than Serialable, so that's the technique I'm using. All the posts are from 2018 or prior and many of them in Java.
How does one send an data class from one Activity to another using Intent?
Since getParcelableExtra (String name) is deprecated from api level 33 you can use getParcelableExtra (String name, Class<T> clazz) from api level 33
In Your case use :
val userData =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
intent.getParcelableExtra("userData", userData::class.java)
}
else{
intent.getParcelableExtra("userData") as userData?
}
where TIRAMISU is constant value 33
To get more info:Read this:
https://developer.android.com/reference/android/content/Intent#getParcelableExtra(java.lang.String,%20java.lang.Class%3CT%3E)
SOLUTION:
Given the need for compiler version 33 for the most modern solution, I went with a more backward compatible solution. This code translates the data object into a string, then back into the object.
SETUP: (PUT)
private var _userData = MutableLiveData<User>() // does the username and pw validate?
val userData : LiveData<User>
get() = _userData
SETUP: (GET)
private lateinit var userData: User
PUT CODE:
val intent = Intent(this, MainActivity::class.java)
val jsonUserData = Gson().toJson(userData)
intent.putExtra("userData",jsonUserData)
GET CODE:
val jsonUserData = intent.getStringExtra("userData")
userData = Gson().fromJson(jsonUserData, User::class.java)

Since ripple-lib-java is unmaintained, how do you manually sign a transaction?

Looking for a lightweight way to manually sign an OfferCreate ... it would be clumsy to start some JavaScript engine in order to get it done.
Hmm ... even though it hasn't been maintained for 4 years it looks like it still works.
Clone ripple-lib-java and do mvn install in ripple-bouncycastle & ripple-core
Then copy the built JARs into <YourProject>/libs
Add local dependencies in Gradle Kotlin DSL:
repositories {
flatDir {
dirs("libs")
}
}
dependencies {
implementation(":ripple-bouncycastle-0.0.1-SNAPSHOT")
implementation(":ripple-core-0.0.1-SNAPSHOT")
runtime("org.json:json:20190722") // No newskool kotlinx-serialization here :(
}
Create & sign OfferCreate:
val offerCreate = OfferCreate()
offerCreate.account(AccountID.fromString("r3jpWpUysF4SAkUNbG4WhDZ5mAJ7rGUDx6"))
offerCreate.expiration(UInt32(get2MinExpiration()))
offerCreate.fee(Amount(BigDecimal("0.00001")))
offerCreate.flags(UInt32(0))
offerCreate.sequence(UInt32(1))
val amountXRP = BigDecimal(200)
val amountBTC = convert(amountXRP, RIPPLE_XRP, BITCOIN)
offerCreate.takerGets(Amount(amountXRP))
offerCreate.takerPays(Amount(amountBTC, Currency.fromString(BITCOIN), AccountID.fromString(BITCOIN_TRUSTED_ISSUER)))
val signedTransaction = offerCreate.sign("[***Secret***]")
println(offerCreate.toJSON())
println(signedTransaction.tx_blob)
A bit annoying that you can't do a toJSON() on a SignedTransaction. It can
t be a security thing, since sign() only adds public key fields: https://xrpl.org/transaction-common-fields.html#signers-field

How do you mock a URL connection in Kotlin?

I've seen a lot of examples on how to mock a connection in Java but haven't seen any explaining how to do it in Kotlin. A bit of code that I want mocked as an example:
val url = URL("https://google.ca")
val conn = url.openConnection() as HttpURLConnection
with(conn) {
//doStuff
}
conn.disconnect()
Similar to a question like this but for Kotlin:
how to mock a URL connection
Kotlin and Java can interop with one another, so you should be able to take your exact example (from the question) provided and convert it to Kotlin (or don't convert it and call the Java directly):
#Throws(Exception::class)
fun function() {
val r = RuleEngineUtil()
val u = PowerMockito.mock(URL::class.java)
val url = "http://www.sdsgle.com"
PowerMockito.whenNew(URL::class.java).withArguments(url).thenReturn(u)
val huc = PowerMockito.mock(HttpURLConnection::class.java)
PowerMockito.`when`(u.openConnection()).thenReturn(huc)
PowerMockito.`when`(huc.getResponseCode()).thenReturn(200)
assertTrue(r.isUrlAccessible(url))
}
It's worth noting that you should probably consider using an actual mocking HTTP server like HttpMocker for handling this as opposed to implement the behavior yourself.

Micronaut declarative client with base url per environment

I'd like to be able to use Micronaut's declarative client to hit an a different endpoint based on whether I'm in a local development environment vs a production environment.
I'm setting my client's base uri in application.dev.yml:
myserviceclient:
baseUri: http://localhost:1080/endpoint
Reading the docs from Micronaut, they have the developer jumping through quite a few hoops to get a dynamic value piped into the actual client. They're actually quite confusing. So I've created a configuration like this:
#ConfigurationProperties(PREFIX)
class MyServiceClientConfig {
companion object {
const val PREFIX = "myserviceclient"
const val BASE_URL = "http://localhost:1080/endpoint"
}
var baseUri: String? = null
fun toMap(): MutableMap<String, Any> {
val m = HashMap<String, Any>()
if (baseUri != null) {
m["baseUri"] = baseUri!!
}
return m
}
}
But as you can see, that's not actually reading any values from application.yml, it's simply setting a const value as a static on the class. I'd like that BASE_URL value to be dynamic based on which environment I'm in.
To use this class, I've created a declarative client like this:
#Client(MyServiceClientConfig.BASE_URL)
interface MyServiceClient {
#Post("/user/kfc")
#Produces("application/json")
fun sendUserKfc(transactionDto: TransactionDto)
}
The docs show an example where they're interpolating values from the config map that's built like this:
#Get("/api/\${bintray.apiversion}/repos/\${bintray.organization}/\${bintray.repository}/packages")
But how would I make this work in the #Client() annotation?
Nowhere in that example do they show how bintray is getting defined/injected/etc. This appears to be the same syntax that's used with the #Value() annotation. I've tried using that as well, but every value I try to use ends up being null.
This is very frustrating, but I'm sure I'm missing a key piece that will make this all work.
I'm setting my client's base uri in application.dev.yml
You probably want application-dev.yml.
But how would I make this work in the #Client() annotation?
You can put a config key in the #Client value using something like #Client("${myserviceclient.baseUri}").
If you want the url somewhere in your code use this:
#Value("${micronaut.http.services.occupancy.urls}")
private String occupancyUrl;

Kotlin enviromental values

I'm learning kotlin, I stumbled across an open-source repo, cloned it and ran on my computer, it is a update tool to update an existing jar, although looking at their code how do they approached to that, they did something like this.
private fun updateJar(frame: LaunchFrame, project: Project) {
val sourcePath = project.jarSourcePath
val jarPath = project.jarPath
val repoName = project.repoName
frame.log("Reading source URL from '$sourcePath'")
val sourceUrl = readTextFile(sourcePath)?.let { URI(it) }
frame.log("Source URL: $sourceUrl")
frame.log("Connecting to GitHub")
val github = GitHub.connectAnonymously()
frame.log("Using repository '$repoName'")
val repo = github.getRepository(repoName)
frame.log("Finding latest release")
val latestRelease = repo.listReleases().first()
val assets = latestRelease.assets
check(assets.size == 1) { "Release must only have one asset" }
val asset = assets.first()
val downloadUrl = URI(asset.browserDownloadUrl)
frame.log("Latest URL: $downloadUrl")
if (sourceUrl == null || sourceUrl != downloadUrl || !verifyJar(jarPath)) {
frame.log("Downloading '$downloadUrl' to '$jarPath'")
downloadFile(downloadUrl, jarPath)
frame.log("Writing '$downloadUrl' to '$sourcePath'")
writeTextFile(sourcePath, downloadUrl.toString())
} else {
frame.log("'$jarPath' is up to date")
}
}
Which looks pretty much straight-forward, but here's the catch, there are no actual URL's for the $sourceUrl and others, can someone shed some light to this question? It starts downloading the repo which is runestar/client but there are no actual links for the exact repo what it's trying to download, so how did they do that?
The values are being extracted using some logic, scattered around various places in the code.
For example, see https://github.com/RuneStar/launcher/blob/3e8dcb59c32d2818c917705c6c4432f9fc12c449/src/main/java/org/runestar/launcher/RuneStar.kt#L15
override val repoName: String get() = "RuneStar/client"
It's not environment variables, and it's not downloading from a URL, it's writing to one on the local filesystem.
The Project interface sets up the file locations and the RuneStar class sets up a specfic Github repository.