Nomin Mapper Framework for Groovy - spring

I am looking for a mapping framework for my Spring/Groovy application. I found Nomin - it looks like something that fits my need. But I have the following issue: it doesn't find my mapping rules script in my test class.
in src/main/groovy/mypackage/entity2entitydto.groovy:
import org.nomin.entity.*
mappingFor a: Entity, b: EntityDto
a.name = b.name
in src/test/groovy/mypackage/Entity2EntityDtoTest.groovy:
public class CoinMarketCap2CoinTest {
NominMapper nomin = new Nomin("entity2entitydto.groovy");
// also tried entity2entitydto, Entity2entitydto, Entity2entitydto.groovy
// also tried with full package name
// also tried File Name Entity2entitydto.groovy
#Test
public void test() {
// Testing ...
}
}
Result after gradle clean build --stacktrace
org.nomin.core.NominException: Specified resource entity2entitydto.groovy isn't found!
...
Someone any idea or suggestions about mapping frameworks which works fine with groovy. Thanks in advance.

Nomin throws this exception, because your script is not in the classpath. Move your entity2entitydto.groovy file to src/main/resources so Nomin can load your mapping script from the classpath correctly.
Secondly, make sure you import correct classes in your mapping script. For example, if I have mypackage.Entity and mypackage.EntityDto class then I can import both of them like:
import mypackage.Entity
import mypackage.EntityDto
mappingFor a: Entity, b: EntityDto
a.name = b.name
Instead you have to use full canonical names like:
mappingFor a: mypackage.Entity, b: mypackage.EntityDto
a.name = b.name
You can also take a look at this very basic and simple example created basing on your question - https://github.com/wololock/nomin-example
Hope it helps.

Related

Problem with Protostream and UUID in Infinispan 13.0.0.Final

I'm using Infinispan 13.0.0.final with the default marshaller (protobuf). When I try to use UUID fields in my datatypes
data class CounterState(
#get:ProtoField(number = 1) var index: Long? = null,
#get:ProtoField(number = 2) var uuid: UUID? = null
)
I get the following error at build time:
.../gradle-kotlin-protobuf/build/tmp/kapt3/stubs/main/io/radiosphere/ProtoSchema.java:8: error: org.infinispan.protostream.annotations.ProtoSchemaBuilderException: The class java.util.UUID must be instantiable using an accessible no-argument constructor.
public abstract interface ProtoSchema extends org.infinispan.protostream.GeneratedSchema {
It seems like I'm not allowed to use UUID in my types unless I generate a protoschema for it, but since UUID is a class outside of my control I can't do this.
Previous questions on the topic have gotten the suggestion to use the JavaSerializationMarshaller, but I want to solve this while still using the Protostream Marshaller. It has also been suggested that this would be fixed in version 12.0.0 here.
An example of this not working can be found here. Note that this project will not build because of the annotation processing failing as mentioned above. If it would build the proof that it is working would be shown by running the main project (ie. not the tests).
The question becomes: What do I need to do to configure UUID to be usable in my protobuf marshalled classes in Infinispan 13? Both for embedded and for a program using the hotrod client?
EDIT:
Based on a given answer I have also tried doing the following:
#AutoProtoSchemaBuilder(
includeClasses = [UUIDAdapter::class, CounterState::class],
schemaPackageName = "tutorial")
interface ProtoSchema : GeneratedSchema {
}
This makes the build work, but when starting Quarkus I get the following error:
Caused by: org.infinispan.protostream.DescriptorParserException: Duplicate type id 1005 for type org.infinispan.protostream.commons.UUID. Already used by tutorial.UUID
at org.infinispan.protostream.descriptors.ResolutionContext.checkUniqueTypeId(ResolutionContext.java:151)
at org.infinispan.protostream.descriptors.ResolutionContext.addGenericDescriptor(ResolutionContext.java:97)
at org.infinispan.protostream.descriptors.FileDescriptor.collectDescriptors(FileDescriptor.java:313)
at org.infinispan.protostream.descriptors.FileDescriptor.resolveDependencies(FileDescriptor.java:245)
at org.infinispan.protostream.descriptors.FileDescriptor.resolveDependencies(FileDescriptor.java:210)
at org.infinispan.protostream.descriptors.ResolutionContext.resolve(ResolutionContext.java:57)
at org.infinispan.protostream.impl.SerializationContextImpl.registerProtoFiles(SerializationContextImpl.java:127)
at org.infinispan.protostream.types.java.CommonTypesSchema.registerSchema(CommonTypesSchema.java:49)
at org.infinispan.client.hotrod.RemoteCacheManager.registerSerializationContextInitializer(RemoteCacheManager.java:422)
at org.infinispan.client.hotrod.RemoteCacheManager.registerDefaultSchemas(RemoteCacheManager.java:437)
at org.infinispan.client.hotrod.RemoteCacheManager.initializeProtoStreamMarshaller(RemoteCacheManager.java:409)
at org.infinispan.client.hotrod.RemoteCacheManager.actualStart(RemoteCacheManager.java:365)
at org.infinispan.client.hotrod.RemoteCacheManager.start(RemoteCacheManager.java:334)
at org.infinispan.client.hotrod.RemoteCacheManager.<init>(RemoteCacheManager.java:192)
at org.infinispan.client.hotrod.RemoteCacheManager.<init>(RemoteCacheManager.java:149)
at io.quarkus.infinispan.client.runtime.InfinispanClientProducer.initialize(InfinispanClientProducer.java:68)
If I instead change to use dependsOn like this:
#AutoProtoSchemaBuilder(
includeClasses = [CounterState::class],
dependsOn = [org.infinispan.protostream.types.java.CommonTypes::class, org.infinispan.protostream.types.java.CommonContainerTypes::class],
schemaPackageName = "tutorial")
I'm back to the build failing with:
error: org.infinispan.protostream.annotations.ProtoSchemaBuilderException: The class java.util.UUID must be instantiable using an accessible no-argument constructor.
public abstract interface ProtoSchema extends org.infinispan.protostream.GeneratedSchema {
It seems to be like Quarkus and the Annotation processor are getting in each others way here when it comes to having a simple working solution for UUID marshalling.
You have to include the org.infinispan.protostream.types.java.util.UUIDAdapter class in your annotation:
#AutoProtoSchemaBuilder(includeClasses = [CounterState::class, UUIDAdapter::class] , schemaPackageName = "tutorial")
For more info, check the documentation page.

Configuring a custom Gradle sourceSet using a closure

I'm trying to develop a Gradle plugin for a language I use (SystemVerilog). I'm still experimenting and figuring things out. Before I write the entire thing as a plugin, I thought it would be best to try out the different parts I need inside a build script, to get a feel of how things should work.
I'm trying to define a container of source sets, similar to how the Java plugin does it. I'd like to be able to use a closure when configuring a source set. Concretely, I'd like to be able to do the following:
sourceSets {
main {
sv {
include '*.sv'
}
}
}
I defined my own sourceSet class:
class SourceSet implements Named {
final String name
final ObjectFactory objectFactory
#Inject
SourceSet(String name, ObjectFactory objectFactory) {
this.name = name
this.objectFactory = objectFactory
}
SourceDirectorySet getSv() {
SourceDirectorySet sv = objectFactory.sourceDirectorySet('sv',
'SystemVerilog source')
sv.srcDir("src/${name}/sv")
return sv
}
SourceDirectorySet sv(#Nullable Closure configureClosure) {
configure(configureClosure, getSv());
return this;
}
}
I'm using org.gradle.api.file.SourceDirectorySet because that already implements PatternFilterable, so it should give me access to include, exclude, etc.
If I understand the concept correctly, the sv(#Nullable Closure configureClosure) method is the one that gives me the ability to write sv { ... } to configure via a closure.
To add the sourceSets property to the project, I did the following:
project.extensions.add("sourceSets",
project.objects.domainObjectContainer(SourceSet.class))
As per the Gradle docs, this should give me the possibility to configure sourceSets using a closure. This site, which details using custom types, states that by using NamedDomainObjectContainer, Gradle will provide a DSL that build scripts can use to define and configure elements. This would be the sourceSets { ... } part. This should also be the sourceSets { main { ... } } part.
If I create a sourceSet for main and use it in a task, then everything works fine:
project.sourceSets.create('main')
task compile(type: Task) {
println 'Compiling source files'
println project.sourceSets.main.sv.files
}
If I try to configure the main source set to only include files with the .sv extension, then I get an error:
sourceSets {
main {
sv {
include '*.sv'
}
}
}
I get the following error:
No signature of method: build_47mnuak4y5k86udjcp7v5dkwm.sourceSets() is applicable for argument types: (build_47mnuak4y5k86udjcp7v5dkwm$_run_closure1) values: [build_47mnuak4y5k86udjcp7v5dkwm$_run_closure1#effb286]
I don't know what I'm doing wrong. I'm sure it's just a simple thing that I'm forgetting. Does anyone have an idea of what that might be?
I figured out what was going wrong. It was a combination of poor copy/paste skills and the fact that Groovy is a dynamic language.
First, let's look at the definition of the sv(Closure) function again:
SourceDirectorySet sv(#Nullable Closure configureClosure) {
configure(configureClosure, getSv());
return this;
}
Once I moved this code to an own Groovy file and used the IDE to show me what is getting called, I noticed that it wasn't calling the function I expected. I was expecting a call to org.gradle.util.ConfigureUtil.configure. Since this is part of the public API, I expected it to be imported by default in the build script. As this page states, this is not the case.
To solve the issue, it's enough to add the following import:
import static org.gradle.util.ConfigureUtil.configure
This will get rid of the cryptic closure related error. It is replaced by the following error, though:
Cannot cast object 'SourceSet_Decorated#a6abab9' with class 'SourceSet_Decorated' to class 'org.gradle.api.file.SourceDirectorySet'
This is caused by the copy/paste error I mentioned. When I wrote the SourceSet class, I drew heavily from org.gradle.api.tasks.SourceSet (and org.gradle.api.internal.tasks.DefaultSourceSet). If we look at the java(Closure) method there, we'll see it has the following signature:
SourceSet java(#Nullable Closure configureClosure);
Notice that it returns SourceSet and not SourceDirectorySet like in my code. Using the proper return type fixes the issue:
SourceSet sv(#Nullable Closure configureClosure)
With this new return type, let's look again at the configuration code for the source set:
sourceSets {
main {
sv {
include '*.sv'
}
}
}
Initially, I thought it was supposed to work as follows: pass main { ... } as a Closure to sourceSets, pass sv { ... } as a Closure to main, and handle the include ... part inside sourceDirectorySet. I banged my head against the wall for a while, because I couldn't find any code in that class hierarchy that takes closures like this.
Now, I think the flow is slightly different: pass main { ... } as a Closure to sourceSets (as initially thought), but call the sv(Closure) function on main (of type sourceSet), passing it { include ... } as the argument.
Bonus: There was one more issue that wasn't related to the "compile" errors I was having.
Even after getting the code to run without errors, it still wasn't behaving as expected. I had some files with the *.svh extension that were still getting picked up. This is because, when calling getSv(), it was creating a new SourceDirectorySet each time. Any configuration that was done previously was getting thrown away each time that this function was called.
Making the sourceDirectorySet a class member and moving its creation to the constructor fixed the issue:
private SourceDirectorySet sv
SourceSet(String name, ObjectFactory objectFactory) {
// ...
sv = objectFactory.sourceDirectorySet('sv',
'SystemVerilog source')
sv.srcDir("src/${name}/sv")
}
SourceDirectorySet getSv() {
return sv
}

Groovy #CompileStatic and #TypeChecked order, bug or misunderstanding

I started getting a strange failure when compiling a gradle task class. This is the task I created:
package sample
import groovy.transform.CompileStatic
import groovy.transform.TypeChecked
import org.gradle.api.artifacts.Dependency
import org.gradle.api.provider.Property
import org.gradle.api.tasks.AbstractCopyTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.bundling.Zip
import sample.internal.DataSourceXmlConfig
#TypeChecked
#CompileStatic
class DataSource extends Zip {
#Internal
final Property<File> warFile = project.objects.property(File.class)
DataSource() {
warFile.convention(project.provider {
def files = project.configurations.getByName('warApp').fileCollection { Dependency d ->
d.name == (archiveFileName.getOrElse("") - (~/\.[^.]+$/))
}
files.empty ? null : files.first()
})
}
/**
* This function is used to specify the location of data-sources.xml
* and injects it into the archive
* #param dsConf The configuration object used to specify the location of the
* file as well as any extra variables which should be injected into the file
*/
#Input
void dataSourceXml(#DelegatesTo(DataSourceXmlConfig) Closure dsConf) {
filesToUpdate {
DataSourceXmlConfig ds = new DataSourceXmlConfig()
dsConf.delegate = ds
dsConf.resolveStrategy = Closure.DELEGATE_FIRST
dsConf.call()
exclude('**/WEB-INF/classes/data-sources.xml')
from(ds.source) {
if (ds.expansions) {
expand(ds.expansions)
}
into('WEB-INF/classes/')
rename { 'data-sources.xml' }
}
}
}
private def filesToUpdate(#DelegatesTo(AbstractCopyTask) Closure action) {
action.delegate = this
action.resolveStrategy = Closure.DELEGATE_FIRST
if (warFile.isPresent()) {
from(project.zipTree(warFile)) {
action.call()
}
}
}
}
When groovy compiles this class, I get the following error:
Execution failed for task ':buildSrc:compileGroovy'.
BUG! exception in phase 'class generation' in source unit '/tmp/bus-server/buildSrc/src/main/groovy/sample/DataSource.groovy'
At line 28 column 28 On receiver: archiveFileName.getOrElse() with
message: minus and arguments: .[^.]+$ This method should not have
been called. Please try to create a simple example reproducing this
error and file a bug report at
https://issues.apache.org/jira/browse/GROOVY
Gradle version: 5.6
Groovy version: localGroovy() = 2.5.4
tl;dr, is this a bug or am I missing something about how these annotations work?
The first thing I tried to do was to remove either one of #TypeChecked and #CompileStatic annotations to see if the error goes away.
This actually fixed the problem right away. Compiling the source with either annotations added was successful, but fails when both are present.
I read some questions and answers regarding the use of both annotations, but none of them seemed to suggest that one cannot use both at the same time.
Finally, I tried switching the order of the annotations to see if that helps and to my surprise, it worked! No compilation errors!
This works:
#CompileStatic
#TypeChecked
class DataSource extends Zip { ... }
At this point, I guess my question would be, is this a bug or is there something I am not understanding about the use of both of these annotations? I'm leaning more towards it being a bug just because of the fact that the order made the error message go away.

ConfigurationProperties loading list from YML

I'm trying to load Configuration from YML. I can load value and I can also load list if these are comma seperated values. But i can't load a typical YML List.
Configuration Class
#Component
#PropertySource("classpath:routing.yml")
#ConfigurationProperties
class RoutingProperties(){
var angular = listOf("nothing")
var value: String = ""
}
Working routing.yml
angular: /init, /home
value: Hello World
Not Working routing.yml
angular:
- init
- home
value: Hello World
Why can't i load the second version of yml / do I have a syntaxt error?
ENV: Kotlin, Spring 2.0.0.M3
As #flyx say, #PropetySource not worked with yaml files. But in spring you may override almost everything :)
PropertySource has additional parameter: factory. It's possible to create your own PropertySourceFactory base on DefaultPropertySourceFactory
open class YamlPropertyLoaderFactory : DefaultPropertySourceFactory() {
override fun createPropertySource(name: String?, resource: EncodedResource?): org.springframework.core.env.PropertySource<*> {
if (resource == null)
return super.createPropertySource(name, resource)
return YamlPropertySourceLoader().load(resource.resource.filename, resource.resource, null)
}
}
And when use this factory in propertysource annotation:
#PropertySource("classpath:/routing.yml", factory = YamlPropertyLoaderFactory::class)
Last that you need is to initialized variable angular with mutableList
Full code sample:
#Component
#PropertySource("classpath:/routing.yml", factory = YamlPropertyLoaderFactory::class)
#ConfigurationProperties
open class RoutingProperties {
var angular = mutableListOf("nothing")
var value: String = ""
override fun toString(): String {
return "RoutingProperties(angular=$angular, value='$value')"
}
}
open class YamlPropertyLoaderFactory : DefaultPropertySourceFactory() {
override fun createPropertySource(name: String?, resource: EncodedResource?): org.springframework.core.env.PropertySource<*> {
if (resource == null)
return super.createPropertySource(name, resource)
return YamlPropertySourceLoader().load(resource.resource.filename, resource.resource, null)
}
}
#SpringBootApplication
#EnableAutoConfiguration(exclude = arrayOf(DataSourceAutoConfiguration::class))
open class Application {
companion object {
#JvmStatic
fun main(args: Array<String>) {
val context = SpringApplication.run(Application::class.java, *args)
val bean = context.getBean(RoutingProperties::class.java)
println(bean)
}
}
}
Kinda old post, i know. But i am at the very same topic right now.
As of now, it seems that PropertySource does indeed work with yaml Files. Given the restriction that it only allows for primitive types (it seems) and it cant handle nested elements. I'm probably gonna dig a bit deeper and update my answer accordingly, but as of now, the accepted answer seems like a functioning workaround.
Well, according to the docs, your YAML file will be rewritten into a property file. The first YAML file becomes:
angular=/init, /home
value=Hello World
While the second one becomes:
angular[0]=init
angular[1]=home
value=Hello World
These are obviously two very different things and therefore behave differently.
Moreover, later in the docs, it is stated that YAML does not even work with #PropertySource:
24.6.4 YAML shortcomings
YAML files can’t be loaded via the #PropertySource annotation. So in the case that you need to load values that way, you need to use a properties file.
That makes me kind of wonder why the first case works for you at all.
The docs say this about the generated …[index] properties:
To bind to properties like that using the Spring DataBinder utilities (which is what #ConfigurationProperties does) you need to have a property in the target bean of type java.util.List (or Set) and you either need to provide a setter, or initialize it with a mutable value, e.g. this will bind to the properties above
So, let's have a look at Kotlin docs: listOf returns a new read-only list of given elements. So the list is not mutable as required by the docs, which I assume is why it doesn't work. Try using a mutable list (since I have never used Kotlin, I cannot give you working code). Also try to declare it as java.util.List if that's possible in Kotlin.

Compiling and Interpreting Packaged Software Assignment - Cant display multilple class outputs

This is a bit involved, and I want to explain this succinctly without making you read a lot, then show the code. I'm not good at that.
Barebones explanation. In this assignment, we are learning, how to compile,interpret in comand prompt, create a package, create a class and sub-classes, import the sub-classes, and execute println commands in all the sub-classes as a single compiled program, and display such in command prompt. I'm missing something, and the subclass println commands don't display when I run GreetingsClass.java, the Superclass. They are all in the same package. The package directory is com.cisp2030.course, and the three Chapters class files exist in a .Chapters folder inside of .course.
First, GreetingsClass.java:
package com.cisp2030.course;
import com.cisp2030.course.Chapters.*;
public class GreetingsClass
{
Chapter1 c1 = new Chapter1();
Chapter2 c2 = new Chapter2();
Chapter3 c3 = new Chapter3();
public static void main(String[] args)
{
System.out.println("$ Greetings, CISP2030!");
System.out.println(c1);
}
}
This is supposed to import and instantiate the variables of the next code contained as Chapter1.class in .Chapters folder.
package com.cisp2030.course.Chapters;
public class Chapter1
{
public Chapter1()
{
System.out.println("Hello from Chapter1!");
}
}
Just imagine that the above code is one of three that range from Chapter1-Chapter3, and they have been compiled by Command Prompt into class files in their respective directory.
The expected output of compiling, interpreting, and running this program in command prompt should be one program which displays all 3-4 println commands. However, at this time, running hte command prompt only displays the one println command. I think this is because I need to sub-class the Chapter classes to GreetingsClass, and having them imported already, somehow direct GreetingsClass to execute the commands of hte Chapters class files, but I don't know how, and I've googled this consistently, and searched through my textbook and am none the wiser. I think I'm missing something in the code itself, but I don't know enough to come up with any ideas. Any help or advice would be greatly appreciated.
Code has been finished:
package com.cisp2030.course;
import com.cisp2030.course.Chapters.*;
public class GreetingsClass
{
public static void main(String[] args)
{
System.out.println("$ Greetings, CISP2030!");
Chapter1 c1 = new Chapter1();
Chapter2 c2 = new Chapter2();
Chapter3 c3 = new Chapter3();
}
}
Does that even compile?
Java doesn't allow static constructors.
public Chapter1() // removed "static"
{
System.out.println("Hello from Chapter1!");
}
c1 is a member of GreetingsClass. In main() you are in a static method, not a method of GreetingsClass and so you can't access it's members. Most obvious solution is to add GreetingsClass greetings = new GreetingsClass(); to main and try to get c1 out of that.

Resources