Optional class in spring boot? - spring-boot

I'm developing an application that manages accounts. I made a Package named org.sid.entities where exists the IBanqueJob interface and below its code
package org.sid.metier;
import org.sid.entities.Compte;
import org.sid.entities.Operation;
import org.springframework.data.domain.Page;
public interface IBanqueMetier {
public Compte consulterCompte(String CodeCompte);
public void verser(String CodeCompte,double mt);
public void retirer(String CodeCompte, double mt);
public void virement(String Cp1, String Cp2, double mt);
public Page<Operation> listOperation(String cp,int page,int size);
}
and the implementation of this interface, below is its code
package org.sid.metier;
import java.util.Date;
import org.sid.dao.CompteRepository;
import org.sid.dao.OperationRepository;
import org.sid.entities.Compte;
import org.sid.entities.Operation;
import org.sid.entities.Versement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service
#Transactional
public class BanqueMetierImpl implements IBanqueMetier {
#Autowired
private CompteRepository compteRepository;
#Autowired
private OperationRepository operationRepository;
#Override
public Compte consulterCompte(String CodeCompte) {
Compte cp = compteRepository.findById(CodeCompte);
if (cp == null)
throw new RuntimeException("compte introuvable");
return cp;
}
i have an error in this line below that says "Type mismatch: cannot convert from Optional to Compte "
Compte cp = compteRepository.findById(CodeCompte);

findById returns an Optional of something, meaning that we either have a single result for a given id or we don't have anything for that.
In order to unpack this Optional, what I usually advise to do is the following:
Compte cp = compteRepository.findById(CodeCompte).orElseThrow(() -> new Exception("Element not found!");
This will throw an exception in case we don't find anything for that specific id.
In some cases is more beneficial to return some default value instead of throwing an exception. In this case we can use this:
Compte cp = compteRepository.findById(CodeCompte).orElse(new Compte());
or with a supplier:
Compte cp = compteRepository.findById(CodeCompte).orElseGet(() -> new Compte());

compteRepository.findById returns an Optional as it implements probably the CrudRepository Interface.
So please use
Optional<Compte> cp = compteRepository.findById(CodeCompte);

Related

Micronaut-Data JDBC - Multiple Dialects for Test and Production

The Mirconaut docs on JDBC repositories clearly tells us we have to create a test repository to test against another dialect. I think this will be manageable (e.g. Postgres for production and H2 for test).
The problem is I have to repeat my methods (e.g. find()) in the test repository. I have a book repository and a test repository:
#JdbcRepository(dialect = Dialect.POSTGRES)
interface BookRepository extends CrudRepository<Book, Long> {
Optional<Book> find(String title);
}
#JdbcRepository(dialect = Dialect.H2)
#Replaces(bean = BookRepository)
#Requires(env = ["test"])
interface TestBookRepository extends BookRepository {
// Optional<Book> find(String title);
// Required to make the find() method appear in the TestBookRepository
}
To make the find() method available in the TestBookRepository, I had to repeat the method (see commented line above).
Is there a better way to avoid repeating myself? The methods from the CrudRepository interface are available in the TestBookRepository without problems. Why is the find() method not treated the same?
BTW, I don't want to mock the test repository. I want to test the repository 'logic' injected by Micronaut-Data against an SQL database.
This is for Micronaut Data 1.0.0.M5, using Groovy for the source.
To make the find() method available in the TestBookRepository, I had
to repeat the method (see commented line above).
I cannot reproduce that behavior. In order for that to be the case I think the java compiler would need to have a bug in it that caused that.
See the project at https://github.com/jeffbrown/mikehoustonrepository.
https://github.com/jeffbrown/mikehoustonrepository/blob/82b8af568042c762a86cef9965e52fdc61053421/src/main/java/mikehoustonrepository/BookRepository.java
// src/main/java/mikehoustonrepository/BookRepository.java
package mikehoustonrepository;
import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;
import io.micronaut.data.repository.CrudRepository;
import java.util.Optional;
#JdbcRepository(dialect = Dialect.POSTGRES)
public interface BookRepository extends CrudRepository<Book, Long> {
Optional<Book> find(String title);
}
https://github.com/jeffbrown/mikehoustonrepository/blob/82b8af568042c762a86cef9965e52fdc61053421/src/test/java/mikehoustonrepository/TestBookRepository.java
// src/test/java/mikehoustonrepository/TestBookRepository.java
package mikehoustonrepository;
import io.micronaut.context.annotation.Replaces;
import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;
#JdbcRepository(dialect = Dialect.H2)
#Replaces(BookRepository.class)
public interface TestBookRepository extends BookRepository{}
https://github.com/jeffbrown/mikehoustonrepository/blob/82b8af568042c762a86cef9965e52fdc61053421/src/main/java/mikehoustonrepository/BookController.java
package mikehoustonrepository;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import java.util.Optional;
#Controller("/books")
public class BookController {
private final BookRepository bookRepository;
public BookController(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
#Get("/")
public Iterable<Book> index() {
return bookRepository.findAll();
}
#Post("/{title}/{author}")
public Book create(String title, String author) {
return bookRepository.save(new Book(title, author));
}
#Get("/find/{title}")
public Optional<Book> findByTitle(String title) {
return bookRepository.find(title);
}
}
https://github.com/jeffbrown/mikehoustonrepository/blob/82b8af568042c762a86cef9965e52fdc61053421/src/test/java/mikehoustonrepository/BookControllerTest.java
package mikehoustonrepository;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
#MicronautTest
public class BookControllerTest {
#Inject
BookClient bookClient;
#Test
public void testFind() throws Exception {
Optional<Book> book = bookClient.find("The Nature Of Necessity");
assertFalse(book.isPresent());
bookClient.create("The Nature Of Necessity", "Alvin Plantinga");
book = bookClient.find("The Nature Of Necessity");
assertTrue(book.isPresent());
}
}
#Client(value="/", path = "/books")
interface BookClient {
#Post("/{title}/{author}")
Book create(String title, String author);
#Get("/")
List<Book> list();
#Get("/find/{title}")
Optional<Book> find(String title);
}
That test passes.
You can see that a different repository is being used for test (TestBookRepository) that is used for other environments (BookRepository).
I hope that helps.
You can utilise Micronaut environments to create different environment configuration for test and production
and configure respective datasource configuration in application-test.yml
and use that datasource for tests
Micronaut Environments from docs
After some more work, I found another way to solve the original problem. You can define a base interface class that just has the methods you need. Then implement concrete classes for the dialect(s) you need. This allows one type of DB for test and one for production.
interface OrderRepository extends BaseRepository, CrudRepository<Order, UUID> {
#Join(value = "product", type = Join.Type.LEFT_FETCH)
Optional<Order> findById(UUID uuid)
}
#JdbcRepository(dialect = Dialect.H2)
#Requires(env = ["test"])
interface OrderRepositoryH2 extends OrderRepository, CrudRepository<Order, UUID> {
}
#JdbcRepository(dialect = Dialect.POSTGRES)
#Requires(env = ["dev"])
interface OrderRepositoryPostgres extends OrderRepository, CrudRepository<Order, UUID> {
}
No methods are needed in the OrderRepositoryH2 interface. Micronaut-data uses the methods from the parent interface fine. The trick is to not use the #JdbcRepository annotation in the parent interface.
You can create any other dialects needed, but you have to make sure the #Requires annotation results in only one bean for any given mode.
I plan to use H2 for testing, with an option to use the Postgres dialect for special test runs when needed.
Sorry for any confusion on the question and comments.
(I decided to mark this as the answer since it solves the original problem).

How to serialize polymorphic list with element type names as xml element names in Jackson

I have a list of objects with common base class. I wish to serialize (and deserialize) this list so that each list element is serialized with its root element equal to the name of the type and not have the wrapping object around the element.
I tried using JsonTypeInfo with Id.Name and As.WRAPPER_OBJECT which produces an XML with proper element names but (obviously) with another layer of XML elements (from the list itself).
package zm.study.xmlserialize.jackson;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
public class JacksonListTest4 {
public static class L {
public List<A> as = new ArrayList<>();
}
#JsonTypeInfo(use = Id.NAME, include=As.WRAPPER_OBJECT)
#JsonSubTypes({
#JsonSubTypes.Type(value=B.class, name="b"),
#JsonSubTypes.Type(value=C.class, name="c"),
})
public static abstract class A {
}
public static class B extends A {
}
public static class C extends A {
}
#Test
public void test() throws Exception
{
L l = new L();
l.as.add(new B());
l.as.add(new C());
new XmlMapper().enable(SerializationFeature.INDENT_OUTPUT)
.writeValue(System.out, l);
}
}
I would like to get:
<L>
<as>
<b/>
<c/>
</as>
</L>
Instead I get:
<L>
<as>
<as>
<b/>
</as>
<as>
<c/>
</as>
</as>
</L>
If you know what you want it to look like you're better off writing an XSD and then using a tool like JAXB to create a serialization/deserialization Java object.

Spring + QueryDsl + Mockito: How to write a unit test case for a simple function

I have the following function in my service.
public boolean checkNameUnique(String name) {
QEntity qEntity = QEntity.entity;
BooleanExpression nameUniquePredicate = qEntity.name.eq(name);
long count = entityReadRepository.count(nameUniquePredicate);
return count == 0;
}
It just checks if the name already exists in db. That needs to be unique, so it returns true if does not already exist and false if it does.
Now how do I write a mockito unit test case for this? I am new to Mockito and writing unit test cases, hence the question.
My reading on Mockito has lead me to write something on the lines of
when(entityReadRepository.count(nameUniquePredicate)).thenReturn(1);
and then call the function to be tested. But that doesn't make any sense.
Entity is Hibernate entity which corresponds to a table in the DB
entityReadRepository extends JpaRepository and QueryDslPredicateExecutor. QEntity is the Q object generated by QueryDsl's plugin.
A unit test would normally mock out any external dependencies, in your case entityReadRepository. If you want to do actual db call it would be classed as integration test.
Your method should return two different values depending on the entityReadRepository response and this is what you would stub in order to unit test it. You were on a good path trying:
when(entityReadRepository.count(any(BooleanExpression.class))).thenReturn(1l);
The problem you have is that you have a lot of static calls and objects in your method and that can't be handled gracefully. One option is to use tools like Powermockito where you can mock behaviour of static methods. If you prefer to stick with mockito you could extract static piece of code to a separate method and create a spy of your class under test:
package com.slavpilus;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
#RunWith(MockitoJUnitRunner.class)
public class TPresenterTest {
#InjectMocks
#Spy
private ClassUnderTest target = new ClassUnderTest();
#Before
public void setUp() {
doReturn(null).when(target).getUniqueNamePredicate();
}
#Mock
private YourRepositoryDependency entityReadRepository;
#Test
public void checkNameUniqueShouldBeTrueIfNameNotInDatabase() {
when(entityReadRepository.count(any())).thenReturn(0l);
boolean isUnique = target.checkNameUnique("anyName");
Assert.assertTrue(isUnique);
}
#Test
public void checkNameUniqueShouldBeFalseIfNameFoundInDatabase() {
when(entityReadRepository.count(any())).thenReturn(1l);
boolean isUnique = target.checkNameUnique("anyName");
Assert.assertFalse(isUnique);
}
}
and your production code would look something like that:
public boolean checkNameUnique(String name) {
BooleanExpression nameUniquePredicate = getUniqueNamePredicate();
long count = entityReadRepository.count(nameUniquePredicate);
return count == 0;
}
protected BooleanExpression getUniqueNamePredicate() {
QEntity qEntity = QEntity.entity;
return qEntity.name.eq(name);
}
This approach however leaves you with some code untested as getUniqueNamePredicate method is skipped entirely during the test execution.

"Cannot resolve symbol" error while implementing method to get data from logged jhipster user

I am a newbie at Java programming and Jhipster framework and maybe my question is an annoying one, but despite the many topics I read on it I can't solve my question. So, I am asking for some help.
In this topic getting the current logged in user in JHipster I found this piece of code:
final Optional<User> isUser = userService.getUserWithAuthorities();
if(!isUser.isPresent()) {
log.error("User is not logged in");
return new Shinything()
}
final User user = isUser.get();
// continue with the user
which is exactly what I need in my class NjdUserConfiguration.java: this class contains a field (User) user and I aim to get NjdUserConfiguration retrieved by logged in user login.
So, firstly, I add to NjdUserConfigurationRepository.java this query annotation:
#Query("select njd_user_configuration from NjdUserConfiguration njd_user_configuration where njd_user_configuration.user =:user")
Optional<NjdUserConfiguration> findOneByUser(#Param("user") User user);
Secondly, I create NjdUserConfigurationService.java like this:
package it.tal.app.service;
import it.tal.app.domain.NjdUserConfiguration;
import it.tal.app.domain.User;
import it.tal.app.repository.NjdUserConfigurationRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
/**
* Service Implementation for managing NdjUserConfiguration.
*/
#Service
#Transactional
public class NjdUserConfigurationService {
private final Logger log = LoggerFactory.getLogger(NjdUserConfigurationService.class);
private final NjdUserConfigurationRepository NjdUserConfigurationRepository;
public NjdUserConfigurationService(NjdUserConfigurationRepository njdUserConfigurationRepository) {
this.NjdUserConfigurationRepository = njdUserConfigurationRepository;
}
/**
* Get one NdjUserConfiguration by user.
*
* #param user the user of the entity
* #return the entity
*/
#Transactional(readOnly = true)
public Optional<NjdUserConfiguration> findOneByUser(User user) {
log.debug("Request to get NdjUserConfiguration : {}", user);
return NjdUserConfigurationRepository.findOneByUser(user);
}
}
Thirdly, I tried to used it in NjdUserConfiguration.java mocking the original code in this new method:
public NjdUserConfiguration getCurrentUser() {
Optional<User> isUser = new UserService.getUserWithAuthorities();
if(isUser.isPresent()) {
//final User user = isUser.get();
return new NjdUserConfigurationService.getOneByUser(isUser.get());
} else {
return null;
}
}
No matter my efforts both getUserWithAuthorities() and getOneByUser(isUser.get()) result in "cannot resolve symbol getUserWithAuthorities()" and "cannot resolve symbol getOneByUser()", though both
import it.tal.app.service.NjdUserConfigurationService;
import it.tal.app.service.UserService;
are present. What did I do so badly or what am I missing?
Thank you
You misuse new operator. Instead of
return new UserService.getUserWithAuthorities();
use
return UserService.getUserWithAuthorities();
assuming UserService is an injected bean.
BTW, java code conventions recommend naming variables so they start with lowercase letter.

Instantiate a field level HashMap in JCodeModel

I want to declare and instantiate a HashMap in one go in JCodeModel.
I do:
jc.field(JMod.PRIVATE, HashMap.class, "initAttributes");
which declares it but doesn't instantiate it. How do I instantiate it?
Thanks
In the simplest case, you can just append the initialization directly to your creation of the field:
jc.field(JMod.PRIVATE, HashMap.class, "initAttributes")
.init(JExpr._new(codeModel.ref(HashMap.class)));
Some further hints:
Considering that you should usually program to an interface, it is a good practice to declare the variable using a type that is "as basic as possible". You should hardly ever declare a variable as
private HashMap map;
but basically always only as
private Map map;
because Map is the interface that is relevant here.
You can also add generics in JCodeModel. These usually involve some calls to narrow on certain types. It is a bit more effort, but it will generate code that can be compiled without causing warnings due to the raw types.
An example is shown here. (It uses String as the key type and Integer as the value type of the map. You may adjust this accordingly)
import java.util.HashMap;
import java.util.Map;
import com.sun.codemodel.CodeWriter;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JMod;
import com.sun.codemodel.writer.SingleStreamCodeWriter;
public class InitializeFieldInCodeModel
{
public static void main(String[] args) throws Exception
{
JCodeModel codeModel = new JCodeModel();
JDefinedClass definedClass = codeModel._class("com.example.Example");
JClass keyType = codeModel.ref(String.class);
JClass valueType = codeModel.ref(Integer.class);
JClass mapClass =
codeModel.ref(Map.class).narrow(keyType, valueType);
JClass hashMapClass =
codeModel.ref(HashMap.class).narrow(keyType, valueType);
definedClass.field(JMod.PRIVATE, mapClass, "initAttributes")
.init(JExpr._new(hashMapClass));
CodeWriter codeWriter = new SingleStreamCodeWriter(System.out);
codeModel.build(codeWriter);
}
}
The generated class looks as follows:
package com.example;
import java.util.HashMap;
import java.util.Map;
public class Example {
private Map<String, Integer> initAttributes = new HashMap<String, Integer>();
}

Resources