import org.litote.kmongo.KMongo
fun main() {
val client = Kmongo.createClient(/* connection string from mongodb */)
val database = client.getDatabase(/* databaseName */)
}
my code ^
this is what it returns:
Exception in thread "main" org.bson.codecs.configuration.CodecConfigurationException: Changing the default UuidRepresentation requires a CodecRegistry that also implements the CodecProvider interface
at org.litote.kmongo.KMongo.createRegistry(KMongo.kt:89)
at org.litote.kmongo.KMongo.createClient(KMongo.kt:78)
at org.litote.kmongo.KMongo.createClient(KMongo.kt:60)
at org.litote.kmongo.KMongo.createClient(KMongo.kt:50)
at MainKt.main(Main.kt:3)
at MainKt.main(Main.kt)
for security purposes, i have omitted the additional code that are irrelevant and the database names
Thanks for your help in advance!
From kmongo source here: https://github.com/Litote/kmongo/blob/master/kmongo-core/src/main/kotlin/org/litote/kmongo/KMongo.kt, it seems that this is happening because the UUID Representation is JAVA_LEGACY.
Hence, you should supply a MongoClientSettings object to createClient, which specifies a UUID representation other than JAVA_LEGACY. Since UuidRepresentation is an enum (https://mongodb.github.io/mongo-java-driver/3.5/javadoc/org/bson/UuidRepresentation.html), you can try using STANDARD.
Like this:
val settings = MongoClientSettings.builder()
.applyConnectionString(ConnectionString("Connection String here"))
.uuidRepresentation(UuidRepresentation.STANDARD)
.codecRegistry(KMongoUtil.defaultCodecRegistry)
.build()
val client = KMongo.createClient(settings)
// other code below...
This should get KMongo/MongoDB to use UuidRepresentation.STANDARD instead of UuidRepresentation.JAVA_LEGACY (in which KMongo will always throw an exception)
Thanks!
Related
I recently switched to Java 11 for a rather big project, and would like to switch to using var class = new Class() instead of Class class = new CLass().
I tried using Intellij Structural Search (and replace) for this, but its turning out to be more complex than expected.
My first attempt was $Type$ $Inst$ = new $Constructor$($Argument$);, which also matches global variables (which don't allow var).
My second attempt is:
class $Class$ {
$ReturnType$ $Method$ ($ParameterType$ $Parameter$) throws $ExceptionType$ {
$Statements$;
final $Type$ $Inst$ = new $Constructor$($Argument$);
$Statements2$;
}
}
Which misses all calls inside e.g. try blocks (since they get matched by the expressions)
Any help would be greatly appreciated!
Use your first template
$Type$ $Inst$ = new $Constructor$($Argument$);
But add a Script modifier on the $Inst$ variable with the following text:
Inst instanceof com.intellij.psi.PsiLocalVariable
Alternatively you may want to try the Local variable type can be omitted inspection that is available in IntelliJ IDEA.
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.
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;
I am using jdbcTemplate to query hive then writing the results to a .csv file. I basically just generate a list of objects then steam the list to write each record to the file.
I will like to stream the results as they coming back from hive and write it to the file instead of wait to get the whole thing then processing it. Can anyone pointing me to the right direction? Thanks!
private List<Avs> queryAvsData(String asSql) {
List<Avs> llistAvs = new ArrayList<Avs>();
List<Map<String, Object>> rows = hiveJdbcTemplate.queryForList(asSql);
Iterator<Map<String, Object>> it = rows.iterator();
while (it.hasNext()) {
Map<String, Object> row = it.next();
Avs laAvs = Avs.builder()
.make((String) row.get("make"))
.model((String) row.get("model"))
.build();
llistAvs.add(laAvs);
}
return llistAvs;
}
It doesn't look like there's a built-in solution, but you can do it. Basically, you wrap the existing functionality in an iterator, and use a spliterator to turn it into a stream. Here's a blog post on the subject:
The code implements Spring’s ResultSetExtractor interface, which is a Single Abstract Method (SAM) interface, allowing the use of a lambda expression to implement it.
The implementation wraps the SQL ResultSet in an iterator, constructs a stream using the Spliterators and StreamSupport utility classes, and applies that to a Function taking a stream of row sets and returning a generic result.
It's possible to stream values from JdbcTemplate. The following example is a service based on Spring Boot 2.4.8.
As, I run into problems (connection leak) using queryForStream then I will put a demo code here just to know that stream must be closed after usage.
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.SingleColumnRowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.stream.Stream;
#Service
#RequiredArgsConstructor
public class DataCleaningService {
private final NamedParameterJdbcTemplate jdbcTemplate;
public void doSomeStreaming() {
String nativeQuery = "SELECT string_value FROM my_table WHERE column = :valueToFiler";
Map<String, Object> queryParameters = Map.of("valueToFiler", "my value");
SingleColumnRowMapper<String> stringRowMapper = SingleColumnRowMapper.newInstance(String.class);
try (Stream<String> stringValueStream = jdbcTemplate.queryForStream(nativeQuery, queryParameters, stringRowMapper)) {
stringValueStream.forEach(stringValue -> {
// do the needed action with the value
//..
System.out.printf("My cool value: %s", stringValue);
});
}
}
}
I'm using HOCON to configure log messages and I'm looking for a way to substitute placeholder values dynamically.
I know that ${?PLACEHOLDER} will read an environment variable and returns an empty string when the PLACEHOLDER environment variable doesn't exist.
Example
This is an example of what I had in mind:
(I'm using config4k to load HOCON )
data class LogMessage(val message: String, val code: String)
fun getMessage(key: String, placeholderValues: Array<String> = arrayOf()): LogMessage {
val config = ConfigFactory.parseString("MY_LOG_MESSAGE {code = ABC-123456, message = My log message with dynamic value %0% and another dynamic value %1% }")
val messageObject = config.extract<LogMessage>(key)
var message = messageObject.message
placeholderValues.forEachIndexed { placeholderIndex, value ->
message = message.replace("%$placeholderIndex%", value)
}
return messageObject.copy(message = message)
}
fun main(args: Array<String>) {
println(getMessage("MY_LOG_MESSAGE", arrayOf("value 1", "value 2")))
// prints: LogMessage(message=My log message with dynamic value value 1 and another dynamic value value 2, code=ABC-123456)
}
Even though this works, it doesn't look like the best solution and I assume there already is a solution for this.
Could someone tell me if there is a built-in solution?
First things first.
HOCON is just a glorified JSON format.
config4k is just a wrapper.
All your work is being done by Typesafe Config, as you've probably noticed.
And judging by their documentation and code, they support placeholders only from withing the file, or from the environment:
This library limits itself to config files. If you want to load config
from a database or something, you would need to write some custom
code.
But for what you're doing, simple String.format() should be enough:
fun interpolate(message: String, vararg args: Any) = String.format(message, *args)
println(interpolate("My message was %s %s %s %s", "a", 1, 3.32, true))
// My message was a 1 3.32 true
Notice that you can use * to destructure your array.