The SonarQube Rule "Fields in a "Serializable" class should either be transient or serializable" is not working properly. I have a very compliant example as mentioned in their rules definition like below, but still it is reported as an issue. I found that there was a bug alreeady raised for this (https://jira.codehaus.org/browse/SONARJAVA-917) and is resolved. And I have the latest version which has this fix as well, but still it is an issue. can some one help me how to resolve this?
`public class Address implements Serializable {
private static final long serialVersionUID = 2405172041950251807L;
}
public class Person implements Serializable {
private static final long serialVersionUID = 1905122041950251207L;
private String name;
private Address address;
}`
Related
I have an entity "MasterSegment" with a composite key as the primary key. This key has a reference to another entity "BkrApplication". When I start the app without Liquibase, tables are generated perfectly and everything works fine.
public class MasterSegment extends Auditable {
#EmbeddedId
private MasterSegmentId id;
#OneToOne
#MapsId("appId")
private BkrApplication app;
// getters setters omitted
}
#Embeddable
public class MasterSegmentId implements Serializable {
#Column
private String name;
#Column(name = "app_id", nullable = false)
private Long appId;
// getters setters omitted
}
The problem is when I try to generate a Liquibase migration using mvn clean install liquibase:diff, I get the following error: Cannot invoke "org.hibernate.mapping.PersistentClass.getTable()" because "classMapping" is null.
Without any hint in the exception message, and after many hours of debugging, I noticed that #MapsId causes the issue. I try to remove it and I got mapping issues.
Any help would be much appreciated.
Thanks
Environment:
spring-boot v2.0.4 RELEASE
spring-data-aerospike v2.0.1.RELEASE
java - 8
Here are my application code and properties.
// application.properties
aerospike.hosts=xxx:3000
aerospike.namespace=test
// aerospike configuration class
#Configuration
#RequiredArgsConstructor
#EnableConfigurationProperties(AerospikeConfiguration.AerospikeConfigurationProperties.class)
#EnableAerospikeRepositories(basePackageClassses = TestAeroRepository.class)
public class AerospikeConfiguration extends AbstractAerospikeDataConfiguration {
private final AerospikeConfigurationProperties aerospikeConfigurationProperties;
#Override
protected Collection<Host> getHosts() {
return Host.parseServiceHosts(aerospikeConfigurationProperties.getHosts());
}
#Override
protected String nameSpace() {
return aerospikeConfigurationProperties.getNamespace();
}
#Data
#Validate
#ConfigurationProperties("aerospike")
public static class AerospikeConfigurationProperties {
#NotEmpty
String hsots;
#NotEmpty
String namespace;
}
}
# Entity class
#Value
#Document
#Builder(toBuilder = true)
#AllArgsConstructor
public class testEntity() {
#Id
int id;
#Field
String name;
#Field
String timestamp;
}
#Repository
public interface TestAeroRepository extends AerospikeRepository<TestEntity, Integer> {
}
public interface TestAeroService {
void save();
}
#Service
#RequiredArgsConstructor
public class TestAeroServiceImpl implements TestAeroService {
private final TestAeroRepository testAeroRepository;
#Override
public void save(TestEntity entity) {
testAeroRepository.save(entity);
}
}
I checked Aerospike client connection has no problem.
But error is occurred when save() method is executed.
org.springframework.cglib.core.ReflectUtils.defineClass(Ljava/lang/String;[BLjava/lang/ClassLoader;Ljava/security/ProtectionDomain;Ljava/lang/Class;)Ljava/lang/Class;
Have to make sets before execute the application? I didn't make sets.
Any problem with my code?
You’re using an old version of spring-data-aerospike (2.0.1.RELEASE was released on April 2019) is there any chance you can upgrade to the latest version? 2.4.2.RELEASE
You can see how to setup a simple spring data aerospike application here: https://medium.com/aerospike-developer-blog/simple-web-application-using-java-spring-boot-aerospike-database-and-docker-ad13795e0089
Please share the entire project’s code and the entire exception.
I would look into:
The configuration class (The Aerospike Beans creation).
The content of the testEntity class - are you using #Id annotation on the primary key field?
Extending the repository class with specifying the testEntity object (… extends AerospikeRepository<testEntity, Object> {) you can see an example in the link I added.
The set is automatically created and takes the name of your object class, which is testEntity in your case. For example, based on your code, if you do not specify a collection in the #Document annotation a set named "testEntity" will automatically be created. I added the #Document(collection = "testEntitys") annotation and all I did was create two set. Once you insert your first record, run the "SHOW SETS" aql command and it will be there. So that's one way to do it.
Probably someone else might have asked something similar as well, but I couldn't find an answer that provides a solution that works...
I'm in the process of learning spring boot and while I was playing with guava RateLimiter during my experiments I hit the following problem:
RateLimiter needs to be created during the Controller initialization, but if I want to load the rate I have to hardcode it, since if I try to load it from props using attributes with #Value Spring annotations it doesn't work.
Is there any "trick" around this "limitation"?
see code below:
#RestController
public class LoggingController {
private Logger logger = LoggerFactory.getLogger(LoggingController.class);
#Value("${count}")
private Double PERMITS_COUNT;
#Value("${seconds}")
private Double PERMITS_PER_SECONDS;
#Value("${consumed}")
private int PERMITS_CONSUMED;
//# Value fails here with NullPointerException
private RateLimiter rateLimiter = RateLimiter.create(PERMITS_COUNT / PERMITS_PER_SECONDS);
// This works file
private RateLimiter rateLimiter = RateLimiter.create(10d / 60d);
private AtomicInteger index = new AtomicInteger(0);
#GetMapping("/logging")
#ResponseBody
public String logging (#RequestParam(name="name", required=false, defaultValue="JavaBoss") String name) {
//#Value works fine if used here
rateLimiter.setRate(PERMITS_COUNT / PERMITS_PER_SECONDS);
rateLimiter.acquire(PERMITS_CONSUMED);
...
Many thanks in advance...
Use PostConstruct and you should be fine
#RestController
public class LoggingController {
private Logger logger = LoggerFactory.getLogger(LoggingController.class);
#Value("${count}")
private Double PERMITS_COUNT;
#Value("${seconds}")
private Double PERMITS_PER_SECONDS;
#Value("${consumed}")
private int PERMITS_CONSUMED;
private RateLimiter rateLimiter;
#PostConstruct
private void createRateLimiter() {
rateLimiter = RateLimiter.create(PERMITS_COUNT / PERMITS_PER_SECONDS);
}
private AtomicInteger index = new AtomicInteger(0);
#GetMapping("/logging")
#ResponseBody
public String logging (#RequestParam(name="name", required=false, defaultValue="JavaBoss") String name) {
...
I have an entity that looks like this
#Entity(name = "encounter_pdf_export")
public class EncounterPDFExport<T extends Encounter> implements Serializable {
public static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long pdfExportId;
#Any(metaColumn = #Column(name = "encounter_type"))
#Cascade(CascadeType.ALL)
#AnyMetaDef(
idType = "long",
metaType = "string",
metaValues = {
#MetaValue(value = "FooEncounter", targetEntity = FooEncounter.class)
})
#JoinColumn(name = "encounter_id")
private T encounter;
The abstract type that I'm extending is:
public abstract class Encounter {
public abstract Long getEncounterId();
}
Here is my Spring Data Repository
#Repository
public interface EncounterPDFExportRepository extends PagingAndSortingRepository<EncounterPDFExport, Long> {
EncounterPDFExport findOneByEncounter_encounterId(#Param("encounterId") Long encounterId);
}
I am getting a stack trace when starting up the application related to to the findOneByEncounter_encounterId method:
Caused by: java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [encounter] on this ManagedType [com.iimassociates.distiller.domain.EncounterPDFExport]
at org.hibernate.jpa.internal.metamodel.AbstractManagedType.checkNotNull(AbstractManagedType.java:144)
at org.hibernate.jpa.internal.metamodel.AbstractManagedType.getAttribute(AbstractManagedType.java:130)
at org.springframework.data.jpa.repository.query.QueryUtils.toExpressionRecursively(QueryUtils.java:468)
at org.springframework.data.jpa.repository.query.JpaQueryCreator$PredicateBuilder.getTypedPath(JpaQueryCreator.java:300)
at org.springframework.data.jpa.repository.query.JpaQueryCreator$PredicateBuilder.build(JpaQueryCreator.java:243)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.toPredicate(JpaQueryCreator.java:148)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.create(JpaQueryCreator.java:88)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.create(JpaQueryCreator.java:46)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createCriteria(AbstractQueryCreator.java:109)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:88)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:73)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.<init>(PartTreeJpaQuery.java:116)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$CountQueryPreparer.<init>(PartTreeJpaQuery.java:237)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:65)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:100)
I am assuming that either Spring Data JPA doesn't support abstracted/generic fields? If that's the case, would creating a #Query be a sufficient workaround?
Not sure if this will be helpful to anyone, but I did get this working.
Removed the abstract class and made it an interface with a single public getEncounterId() method
Modified FooEncounter to implement the above interface
Removed generics from the EncounterPDFExport class
Modified the encounter field to utilize the above interface rather than a generic
Apparently, I'm hitting some Hibernate bug/limitation when accessing fields within FooEncounter. Accessing Encounter within EncounterPDFExport works OK, though. I modified my Spring Data JPA Repository to look like the following (note the modification from finding by encounter.encounterId vs. just encounter):
#Repository
public interface EncounterPDFExportRepository extends PagingAndSortingRepository<EncounterPDFExport, Long> {
EncounterPDFExport findOneByEncounter(#Param("encounter") Encounter encounter);
}
The Hibernate bug in question seems to be related to https://jira.spring.io/browse/DATAJPA-836.
If I use the Lombok #Setting annotation on a field with a value of PRIVATE
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Notification implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Setter(value = AccessLevel.PRIVATE)
private String id;
private long userId;
private Event event;
private long timestamp = System.currentTimeMillis();
public Notification(final String id) {
this.id = id;
}
}
The Sonar Maven plugin gives the following error:
ERROR] Failed to execute goal org.codehaus.mojo:sonar-maven-plugin:2.7.1:sonar (default-cli) on project mio-events: Unable to analyze .class file tv/nativ/mio/event/model/Notification: 0 is not a valid line for a file -> [Help 1]
Changing the #Setting value to public fixes the issue, as does removing #Setting altogether and adding a manual private setter for the field.
Any idea what the issue might be?
Thanks
Nick
Sonar doesn't really support Lombok: Feature request for lombok like tools
Prior to running sonar you should delombok the source and use the generated sources for analysis. Information about this is on the page: Delombok. If you are using maven there's an example of using this technique here: Example Pom