I've lost an entire day trying to understand what is going on and find a fix. I have a JPA mapped entity that, besides other properties, has the following:
#Entity
#Table(name = "xyz")
data class XYZ(
...
#Column(name = "status", nulable = false)
#Enumerated(EnumType.STRING)
private var initialStatus: XYZStatus,
...
) {
#Transient
var status: XYZStatus = initialStatus
get() = initialStatus
set(nextStatus) {
...
initialStatus = nextStatus
field = nextStatus
}
}
This have been working forever, since this class was first created. Now the situation is that everytime I run my integration tests on Intellij IDEA (Ultimate 2018.2) they fail because the Spring context cannot be created. The error is: Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: model.XYZ column: status (should be mapped with insert="false" update="false").
The bizarre part: this error happens only on my machine, only when running the tests from inside the IDE. If I run the tests via Maven on the command line it is ok. I already tried to change the field name from status to something else and the error just changes for the "something else" name I give to the variable.
I already removed and cloned my repo again. Already removed and reinstalled Intellij. I really don't know what can be the source of this error. Any ideas?
Thanks!
Related
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.
Currently using reddison, creating a redissonClient and trying to poll data from redis server. I can see the data in the redis db if I check via redis-cli but when I look at the string value in my java application it is always the first 8 characters of the string and no more. Not sure why it won't give me the whole value.
I've tried using the .peek() method as well and I see the same symptom in that I only get 8 characters of the string returned.
Here is the main part of the code I can provide more details as needed:
#Service
#Slf4j
public class RedisConsumer {
RedisConfig redisConfig;
//RQueue<String> redisQueue;
RBlockingQueue<String> redisQueue;
#Autowired
RedisConsumer(RedisConfig redisConfig) {
this.redisConfig = redisConfig;
}
public void pollAuditQueue() {
//Redisson
redisQueue.add("{JSON string here snipped out for brevity}");
String item = redisQueue.poll();
if (!Objects.isNull(item)) {
log.info("I found this item: " + item);
} else {
log.info("Nothing in queue...");
}
}
#PostConstruct
private void init() throws Exception {
RedissonClient redissonClient = redisConfig.redisson();
redisQueue = redissonClient.getBlockingQueue("test");
while(true) {
pollAuditQueue();
Thread.sleep(5000);
}
}
When I look at the print statement in my console I see:
I found this item: {"AuditEv
When I check the redis-cli I can see the whole value:
1) "\xfc\t{\"AuditEvent\":{\"timestamp\":\"2018-11-27 04:31:47.818000+0000\" snipped the rest out for brevity}"
Lastly if I check that the item was removed from Redis after being polled in the Java app I can confirm that it is.
Any help would be great since it's not throwing any specific error I'm not finding any resources online to help address it.
I've found one thing I didn't notice in my earlier testing. When I manually insert using the redis cli I was replicating what my first tests through Java did which put the \xfc\t at the front which can be seen in my sample above.
Just now when I used redisQueue.add from within my application I noticed in redis it has \xfc\x80\x90\x01 instead and those do return the entire string to me in my application. I assume then this has to do with memory allocation somehow? I'm marking the question as resolved as I am no longer experiencing the issue. If anyone can drop on comment on what those letter/numbers mean though it may be meaningful for anyone that reads this post later. Once I have researched it I will add that comment myself if no one has beat me to it!
Add encoding:
RMap map = redisson.getMap("SessionMap"); -->
RMap map = redisson.getMap("SessionMap", new StringCodec("UTF-8"));
At startup, I check for some data and if not present attempt to save some defaults (temporarily for testing).
val subs = repo.findAll().toIterable()
if(subs.none()) {
repo.saveAll(defaults.map { Source(it.link.hashCode().toLong(), it::class.java.canonicalName, arrayOf(it.link)) }).blockLast()
}
On the first run, we will reach the saveAll() but never unblock. The data is saved in MongoDB, and I can confirm it with Robo 3t.
Subsequent runs with data actually present will lead to the first findAll never unblocking.
Profiling in MongoDB appears to show a successful query.
Profile of findAll() query
My Respository and Entity are as follows:
interface SourceRepository : ReactiveCrudRepository<Source, Long> {
//
}
data class Source(
#Id val id: Long,
val type: String,
val params: Array<String>
)
This is in Kotlin, against Spring Boot 2.0.0.M4. I am targeting a MongoDB instance running in docker. If I remove this bit of startup logic, my other ReactiveCrudRepository is able to read/write just fine, never blocking.
The working Repository's saveAll() call also concludes in a blockLast(), as I found that without this the save would never actually occur.
We are using spring 3 and struts 2. We use spring #value annotation to get values from property files.
We want to get validation rules from property files instead of hard-coding them in action.
Here is sample property
system.properties
transfer.account.min.amount=10
Here is the action:
public class TransferToAccount implements Preparable {
#Value("${transfer.account.min.amount}") public String minAmount;
//...........execute and other methods omitted
#IntRangeFieldValidator(type = ValidatorType.FIELD, min = "${minAmount}", key = "validate.int.min")
public void setAmount(Integer amount) {
this.amount = amount;
}
The minAmount is populated correctly by value 10, but the validation is not working.
To see if parameters are passed correctly, I make a test as below.
Assume we want to get a key from spring managed property file ( This is just a test ;) )
system.properties
transfer.account.min.amount.key=validate.int.min
The resource bundle is:
validate.int.min = This field must be more than ${min}
...and we change validation as below:
#IntRangeFieldValidator(type = ValidatorType.FIELD, min = "${minAmount}", key = "${transfer.account.min.amount.key}")
Now when an error happens the validation message shows validate.int.min, instead of fetching this value from resource bundle!
Of course, when you run below code:
#IntRangeFieldValidator(type = ValidatorType.FIELD, min = "${minAmount}", key = "validate.int.min")
The error message is fetched resource bundle correctly!
If I can use annotation in this way, please let me know what is my mistake!
If I can not use annotations like this, please let me know what is the best way to avoid hard coding the validaiton rolls in actions.
I know this question has been asked numerous times but I couldn't find a suiting answer for me.
I've got two entities in a Spring Roo-application which are in a Many-To-Many-relationship, Release and Component.
First I fetch an instance of an existing Release via
selectedRelease = Release.findReleasesByReleaseNumberEquals(version).getSingleResult();
The method above is a Roo-generated finder which looks like this:
public static TypedQuery<Release> Release.findReleasesByReleaseNummerEquals(String releaseNumber) {
EntityManager em = Release.entityManager();
TypedQuery<Release> q = em.createQuery("SELECT o FROM Release AS o WHERE LOWER(o.releaseNumber) LIKE LOWER(:releaseNummer)", Release.class);
q.setParameter("releaseNumber", releaseNumber);
return q;
}
Then I create a new instance of Component and try to assign it to the selected Release
Component component = new Component();
Set<Release> releases = new HashSet<Release>();
releases.add(selectedRelease);
component.setReleases(releases);
component.persist();
Upon trying to execute persist() I get the exception:
TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.Release;
Does anyone have advice regarding this problem?
The mappings look like this:
Release.java:
#ManyToMany(cascade = CascadeType.PERSIST, mappedBy = "releases")
private Set<Component> components = new HashSet<Component>();
Component.java
#ManyToMany(cascade=CascadeType.PERSIST)
private Set<Release> releases = new HashSet<Release>();
The message is clear: you are trying to save an object, component, that references another object that hasn't been saved yet, selectedRelease.
The solution seems to be easy: just save (and flush whenever you want the changes be comunicated to the database) the Release objects before saving the Component.
However, JPA allows you to avoid all these sentences with TRANSITIVE PERSISTENCE, that is, the cascade options in the #...ToMany annotations.
Just a warning in case you have a bidirectional relationship, when you have a mappedBy attribute in one of the #...ToMany associations. In this case, you'll need a convenient method to manage the association, that is, to set both sides of the association.
For instance, an addRelease(Release r) in Component that both adds the release to the component's set, and sets the component (actually, the this instance) to the release passed as parameter.