cassandra-driver-mapping: InvalidTypeException: Invalid 32-bits float value, expecting 4 bytes but got 6 - spring-boot

As I got issues with spring-data-cassandra with docker as describer here I switched to use com.datastax.cassandra library for cassandra operations but I am getting issues while mapping the resulted object using entity mapper as per this link
Here is my code ...
public String getUser(String userName) {
Mapper<User> mapper = manager.mapper(User.class);
User result = mapper.get(userName); // no issue getting User
String accountNum = result.getAccountId();
return accountNum ;
}
public Account getAccount(String accountNum){
Mapper<Account> mapper = manager.mapper(Account.class);
Account account = mapper.get(accountNum); // getting error here
return account;
}
Account.java
#Table(name = "account")
public class Account {
#PartitionKey
private String accountNum;
private String accountsubtype;
private float currentbalance;
private String customertype;
private String firstname;
private boolean isactive;
private String payments;
private String status;
....
//Getters & Setters
}
pom.xml dependecies
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-mapping</artifactId>
<version>3.0.0</version>
</dependency>

Related

Spring Boot User Validation

I need a custom validator in Spring Boot(version 2.7.x). My User class is defined as:
class User{
private String email;
private String phone;
private String name;
private String address;
private String city;
private String country;
private String postalCode;
//getters and setters
}
I'm trying to validate the following requirements:
Either phone or email or a combination of (name+address+city+country+postalCode) is mandatory
If (name+address+city+country+postalCode) is present, they should be not null.
Please help with your suggestions as to how do I go about in implementing it.
you can use JSR-303 valiation implementation that hibernate-validator
and it is conventient to use annotation for valiate which
is in package javax.validation.constraints
here is code sample that
you can use #NotNull annotation above Field that mark the field should be not null
entity
class User{
private String email;
private String phone;
private String name;
#NotNull(message = "address should be not null")
private String address;
private String city;
private String country;
private String postalCode;
//getters and setters
}
validatorUtil
#Slf4j
public class ValidatorUtil {
static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public static <T> Set<ConstraintViolation<T>> validateOne(T t , Class<?>... group) {
Set<ConstraintViolation<T>> validateResult = validator.validate(t,group);
return validateResult;
}
}
valiatorTest
#Slf4j
public class ValiatorTest {
#Test
public void vailator(){
User accountInfo = new User();
Set<ConstraintViolation<User>> constraintViolations = ValidatorUtil.validateOne(accountInfo);
Assertions.assertTrue(CollectionUtil.isNotEmpty(constraintViolations));
}
}
if you build project with maven ,add hibernate-validator dependency to pom
<properties>
<hibernate.validator.version>6.0.14.Final</hibernate.validator.version>
</properties>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate.validator.version}</version>
</dependency>
if you want learn more , please accroding to this article Which #NotNull Java annotation should I use?!

Why lombok do not create the setters and getters?

I am new to Spring Boot framework and lombok.
I defined my entity like that:
#Entity
#Table(name = "student")
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
public class Student implements Serializable{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String firstName;
private String lastName;
private String email;
}
I also create a controller where I add the following:
#PostMapping(path="/add") // Map ONLY POST Requests
public #ResponseBody String addNewUser (#RequestParam String name
, #RequestParam String email) {
// #ResponseBody means the returned String is the response, not a view name
// #RequestParam means it is a parameter from the GET or POST request
Student st = new Student();
st.setFirstName(name);
st.setEmail(email);
//studentservice.save(st);
return "Saved";
}
I dont know why I have a red line under setFirstName. They ask me to create this function in the student class.
I am using eclipse.
please follow the steps as below:
check pom.xml for lombok dependency
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
Now you can check your IDE,
I hope, it helps!

Quarkus Reactive with Vert.x and Hibernate Reactive / java.lang.NullPointerException: Cannot store to object array because "this.loadedState" is null

i am trying to use quarkus reactive with vert.x and hibernate reactive.
this is my pom.xml:
<quarkus-plugin.version>1.12.2.Final</quarkus-plugin.version>
and
<quarkus.platform.version>1.12.2.Final</quarkus.platform.version>
with:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-mysql-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx-web</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-reactive</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
this is my application.properties file:
# postgres-configuration
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=partner_usr
quarkus.datasource.password=postgrespw
quarkus.datasource.reactive.url=vertx-reactive:postgres://localhost:3310/partnerdb
# test, but not working (schema's won't created)
quarkus.hibernate-orm.database.generation.create-schemas=true
# working (drop-and-create only on mysql, not on postgres)
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.log.sql=true
quarkus.http.cors=true
Then, i have following entities:
#Data
#MappedSuperclass
public abstract class IdEntity {
#Id
#SequenceGenerator(name = "entitySeq", sequenceName = "entitiy_id", allocationSize = 1, initialValue = 5)
#GeneratedValue(generator = "entitySeq", strategy = GenerationType.AUTO)
private Long id;
}
#Data
#Entity
#EqualsAndHashCode(callSuper = true)
public class Person extends IdEntity {
private String firstName;
private String lastName;
public Person() {
}
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Address personAddress;
}
#Data
#Entity
#EqualsAndHashCode(callSuper = true)
public class Address extends IdEntity {
private String street;
private String houseNumber;
private int postalCode;
private String city;
#OneToMany(orphanRemoval = true, mappedBy = "personAddress", fetch = FetchType.LAZY)
private List<Person> persons = new ArrayList<>();
public Address() {
}
}
Now, i am calling a reactive web-service with a reactive db access:
#Path("/person")
#ApplicationScoped
public class PersonResource {
#Inject
io.vertx.mutiny.pgclient.PgPool sqlClient;
#Inject
Mutiny.Session mutinySession;
#GET
//#Produces(MediaType.APPLICATION_JSON)
#Path("/list-persons")
#Route(path = "/list-persons", methods = HttpMethod.GET, produces = MediaType.APPLICATION_JSON)
#Transactional
public Multi<Person> listAllPersons() {
// return sqlClient.query("SELECT * FROM Person ORDER BY lastName ASC").execute()
// .onItem().transformToMulti(set -> Multi.createFrom().iterable(set))
// .onItem().transform(this::transformPersons);
return mutinySession.createQuery("SELECT f FROM Person f ORDER BY f.lastName")
.getResults().onItem().transform(this::transformObject);
}
private Person transformObject(Object f) {
return (Person)f;
}
private List<Object> transformPersons(Object f) {
final Person person = (PartnerMockEntity)f;
final List<Object> bogus = new ArrayList<>();
bogus.add(partner);
return bogus;
}
}
Exception:
Resulted in: com.fasterxml.jackson.databind.JsonMappingException: Cannot store to object array because "this.loadedState" is null (through reference chain: de.subito.model.Person["personAddress"]->de.subito.model.Address["person"])
I tried to use :
FetchType.EAGER on Address in Person
I removed the #OneToMany Relation in Address: this solves the error (yay), but the addresses won't be returned in the resulting json (id is existing, but the values are not fetched)
The questions is, how can i fetch in reactive those kind of relations without getting errors?
Or do i need a angular page in order to display this correctly?
Somehow i forgot about how fetchType.Lazy works.
Simply add a join fetch into the hql and everything works as expected.
SELECT p from Person p left join fetch p.personAddress
When using this query, there's no session/closed or any other exception thrown and the json result will be displayed as expected.
Additional note: in order to avoid recursive serialization, it is required to use the
#JsonManagedReference and #JsonBackReference
Annotations, depending on your needs to your relations.

Spring boot liquibase. Execute DIFF between entities and database

I am trying to set up liquibase in my spring boot application. What I am trying is to create change sets between my Entities and my DB with mvn liquibase:diff
Here is example of one of my entities:
package com.example.start.project.entity;
import static com.example.start.project.entity.DatabaseConstants.CREATED_AT;
import static com.example.start.project.entity.DatabaseConstants.CREATED_BY;
import static com.example.start.project.entity.DatabaseConstants.LEGACY_ID;
import static com.example.start.project.entity.DatabaseConstants.MODIFIED_AT;
import static com.example.start.project.entity.DatabaseConstants.MODIFIED_BY;
import static com.example.start.project.entity.DatabaseConstants.SCHEMA_NAME;
import static com.example.start.project.entity.DatabaseConstants.TABLE_PREFIX;
import static com.example.start.project.entity.PlantEntity.TSN_PREFIX;
import java.time.ZonedDateTime;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.data.annotation.Immutable;
#Entity
#Table(schema = SCHEMA_NAME, name = TABLE_PREFIX + TSN_PREFIX + "PLANT")
#Immutable
public class PlantEntity {
/** Table short name. */
static final String TSN = "PLNT";
/** Table short name as prefix. */
static final String TSN_PREFIX = TSN + "_";
/** Id column name */
static final String ID_COLUMN = TSN_PREFIX + DatabaseConstants.ID;
private static final long serialVersionUID = 1L;
#Id
#Column(name = ID_COLUMN)
private UUID id;
#Column(name = TSN_PREFIX + LEGACY_ID)
private Long legacyId;
#Column(name = TSN_PREFIX + "NUMBER")
private String number;
#Column(name = TSN_PREFIX + "NAME")
private String name;
#Column(name = TSN_PREFIX + "TYPE")
private String type;
#Column(name = TSN_PREFIX + CREATED_BY)
private String createdBy;
#Column(name = TSN_PREFIX + CREATED_AT)
private ZonedDateTime createdAt;
#Column(name = TSN_PREFIX + MODIFIED_BY)
private String modifiedBy;
#Column(name = TSN_PREFIX + MODIFIED_AT)
private ZonedDateTime modifiedAt;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public Long getLegacyId() {
return legacyId;
}
public void setLegacyId(Long legacyId) {
this.legacyId = legacyId;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public ZonedDateTime getCreatedAt() {
return createdAt;
}
public void setCreatedAt(ZonedDateTime createdAt) {
this.createdAt = createdAt;
}
public String getModifiedBy() {
return modifiedBy;
}
public void setModifiedBy(String modifiedBy) {
this.modifiedBy = modifiedBy;
}
public ZonedDateTime getModifiedAt() {
return modifiedAt;
}
public void setModifiedAt(ZonedDateTime modifiedAt) {
this.modifiedAt = modifiedAt;
}
}
And here is my POM looks like:
*******
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.8.8</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-cdi</artifactId>
<version>3.8.8</version>
</dependency>
<dependency>
<groupId>org.liquibase.ext</groupId>
<artifactId>liquibase-hibernate5</artifactId>
<version>3.8</version>
</dependency>
</dependencies>
</dependencyManagement>
*********
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.8.8</version>
<configuration>
<propertyFile>liquibase/liquibase.properties</propertyFile>
<changeLogFile>liquibase/changeLogs/database.yaml</changeLogFile>
<driver>${test.jdbc.driver}</driver>
<url>${test.jdbc.url}?currentSchema=${test.jdbc.schema}</url>
<username>${test.jdbc.userName}</username>
<password>${test.jdbc.password}</password>
<!--defaultSchemaName>${test.jdbc.schema}</defaultSchemaName>-->
<changelogSchemaName>${test.jdbc.schema}</changelogSchemaName>
<referenceDriver>liquibase.ext.hibernate.database.connection.HibernateDriver</referenceDriver>
<referenceUrl>hibernate:spring:com.example.start.project.entity?dialect=org.hibernate.dialect.PostgreSQL95Dialect</referenceUrl>
<diffChangeLogFile>${project.build.directory}/startup.db-diff.yaml</diffChangeLogFile>
<outputChangeLogFile>${project.build.directory}/db-initial.yaml</outputChangeLogFile>
<!-- Syntax: [objecttype from liquibase.structure.core]:[regex matching name] -->
<diffExcludeObjects>sequence:.*_SEQ</diffExcludeObjects>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
<logging>debug</logging>
</configuration>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>update</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>${test.jdbc.groupId}</groupId>
<artifactId>${test.jdbc.artifactId}</artifactId>
<version>${test.jdbc.version}</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>${java-validation-api.version}</version>
</dependency>
<dependency>
<groupId>org.liquibase.ext</groupId>
<artifactId>liquibase-hibernate5</artifactId>
<version>${liquibase.hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</pluginManagement>
</build>
When I run mvn liquibase:diff i got No changesets to add. even I have few entities and my DB is empty. DB is Postgress.
I think that issue is with referenceUrl:
<referenceUrl>hibernate:spring:com.example.start.project.entity?dialect=org.hibernate.dialect.PostgreSQL95Dialect</referenceUrl>
and that liquibase is not able to find my entities.
Entities are placed in different maven module than from where I am running mvn liquibase:diff but this module has reference to it.
Does anyone see what I am doing wrong. Thanks in advance.
You can add this liquibase plugin with a path to liquibase properties file:
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<propertyFile>src/main/resources/liquibase.properties</propertyFile>
</configuration>
</plugin>
And liquibase.properties should look like this:
url=jdbc:oracle:thin:#1.1.1.1:1521:ORCL
username=name
password=pas
driver=oracle.jdbc.driver.OracleDriver
outputChangeLogFile=src/main/resources/liquibase-outputChangeLog.xml
changeLogFile=classpath:/db/changelog/db.changelog-master.xml
referenceUrl=hibernate:spring:com.your.model?dialect=org.hibernate.dialect.Oracle12cDialect
diffChangeLogFile=target/db.changelog-diff.xml
Then: mvn liquibase:diff

Spring Boot testing with H2 - Table "OAUTH_ACCESS_TOKEN" not found

I'm thinking I need to setup the db testing environment (e.g. create tables, seed users so that token can be issued with credentials) before I can run tests but not sure how to.
#RunWith(SpringRunner.class)
#WebAppConfiguration
#SpringBootTest(classes = Application.class)
public class UsersControllerTest {
// ...
private MockMvc mockMvc;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
.addFilter(springSecurityFilterChain).build();
}
private String obtainAccessToken(String username, String password) throws Exception {
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("client_id", CLIENTID);
params.add("grant_type", CLIENTPASSWORD);
params.add("username", username);
params.add("password", password);
ResultActions result = mockMvc.perform(post("/oauth/token")
.params(params)
.with(httpBasic(CLIENTID, CLIENTPASSWORD))
.accept("application/json;charset=UTF-8"))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json;charset=UTF-8"));
String resultString = result.andReturn().getResponse().getContentAsString();
JacksonJsonParser jsonParser = new JacksonJsonParser();
return jsonParser.parseMap(resultString).get("access_token").toString();
}
#Test
public void givenNoToken_whenGetAllUsers_thenUnauthorized() throws Exception {
mockMvc.perform(
get("/users")
).andExpect(status().isUnauthorized());
}
#Test
public void givenToken_whenGetAllUsers_thenOk() throws Exception {
String accessToken = obtainAccessToken("martyn", "secret");
mockMvc.perform(
get("/users")
.header("Authorization", "Bearer " + accessToken)
).andExpect(status().isOk());
}
// ...
Here is a typical Entity for this app:
#Entity(name = "users")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = -8507204786382662588L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable = false)
private String firstName;
#Column(nullable = false)
private String surname;
#Column(nullable = false, unique = true)
private String email;
#Column(nullable = false, unique = true)
private String username;
#Column(nullable = false)
#JsonIgnore
private String password;
#OneToMany
#JoinColumn(name="user_id") // cascade = CascadeType.ALL, orphanRemoval = true
private List<Fund> funds;
public Long getId() {
return id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
// standard getters and setters
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Fund> getFunds() {
return funds;
}
}
But also, as the error indicates, I'd need to generate these oauth* tables too.
Here is my src/test/resources/application.properties
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
So I guess I want to generate the tables (entities, and oauth*) in the H2 database prior to running tests and populate with a single user(?) but can't seem to figure how this is done in Spring Boot. Or should I not be hitting any database and mocking JDBC altogether? Could someone point me in the correct direction as to how to prepare a test environment here? I'm at a bit of a loss.
UPDATE
Here is how dataSource is configured:
#Configuration
public class JDBCTokenConfig {
#Value("${spring.datasource.url}")
private String datasourceUrl;
#Value("${spring.datasource.username}")
private String dbUsername;
#Value("${spring.datasource.password}")
private String dbPassword;
#Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(datasourceUrl);
dataSource.setUsername(dbUsername);
dataSource.setPassword(dbPassword);
return dataSource;
}
#Bean
public TokenStore tokenStore(DataSource dataSource) {
return new JdbcTokenStore(dataSource);
}
// #Bean
// public TokenStore tokenStore() {
// return new InMemoryTokenStore();
// }
}
pom.xml
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
...
</dependencies>
I think it is a good thing to reach your in memory database without mocking. Honestly, you will need more time to configure rather than creating the correct schema needed for your database.
Using Spring-boot, it is very easy to configure to test your application:
Declare using spring-boot-starter-jpa
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Add the in memory DB for your tests
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
Delete your spring.datasource properties in application.properties
Thanks to #SpringBootApplication, the datasource will be automatically configured to connect to your H2 in memory database.
Create the SQL schema
By default, spring-boot-starter-jpa configures automatically the datasource to execute scripts classpath:/schema.sql and if you need also, classpath:/data.sql.
Create a schema.sql in src/test/resources, and create the tables (copy the following content, I think this is what you need: https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql) (I am not sure for this, maybe hibernate creates your schema on his own).
Create your schema in src/test/resources/schema.sql and seed the users in src/test/resources/data.sql
Check also the spring documentation to know how you can configure hibernate :
https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#data-properties
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#reference
Now I understand, which is everybody, that you need to have your configuration different dependending on your environment. The best to do that is to rely on profiles.
In your situation, you have a prod profile, and a test profile.
Declare the profile and keep your spring.datasource properties in your src/test/resources/application.properties (the easier in your case I think)
I suggest you to read this Configure specific in memory database for testing purpose in Spring, and let me know if you have troubles configuring your environment.
With this, you will need to:
Add an annotation at the top of your Test class #ActiveProfiles('test')
Restore the spring.datasource properties you previously deleted an put them in src/test/resources/application-test.properties
Let me know

Resources