Spring Boot Isolation.SERIALIZABLE not working - spring

I need help with this scenario, in theory the isolation level of Serializable should stop delete from happening, but in this scenario it still deletes the row with id 1, I have tried #EnableTransactionManagement and isolation repeatable read, it still doesn't block the delete nor cause the delete to throw exception
In summary, I need to stop any delete invocation whenever the update method is still ongoing
I am using H2 in memory database for this sample
Thanks
Entity:
public class Something {
#Id
private Integer id;
private String name;
private String desc;
}
Repo:
public interface SomeRepository extends JpaRepository<Something, Integer> {
}
Service:
#Service
public class SomeService {
#Autowired
private SomeRepository someRepository;
public void deleteSomething2(Something something) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
someRepository.delete(something);
}
#Transactional(isolation = Isolation.SERIALIZABLE)
public void updateSomething2(Something something) {
Something something1 = someRepository.findById(1).get();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
something1.setName("namanama");
someRepository.saveAndFlush(something1);
}
Test:
#RunWith(SpringRunner.class)
#SpringBootTest
public class DemoApplicationTests {
#Autowired
private SomeService service;
#Test
public void test() throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(10);
List<Future> futures = new ArrayList<>();
futures.add(executorService.submit(() -> service.updateSomething2(Something.builder().id(1).name("namaone").build())));
futures.add(executorService.submit(() -> service.deleteSomething2(Something.builder().id(1).build())));
while(futures.stream().filter(f -> f.isDone() == false).count() > 0) {
Thread.sleep(3000);
}
List<Something> all = service.findAll();
System.out.println(all);
}
}

Related

#Transactional timeout is not working in spring boot application

I am using Spring Boot and JdbcTemplate in my application. I am trying to implement timeout for select query but its not working.
My query takes more time than timeout time but still its not giving timeout exception.
#Service
#Slf4j
public class SchedulerService
{
#Autowired
UserService userExportService;
#Autowired
private userExportDao userExportDao;
#Value("${queryTest}")
private String queryFetchByExportFlagCustom;
#Scheduled(fixedDelay=10000)
public void triggerUserExport() {
List<UserExportCustom> userList;
try {
userList = userExportDao.findByExportFlag(0, queryFetchByExportFlagCustom);
userExportService.exportUsers(userList, schedulerCount);
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Repository
#Slf4j
public class UserExportDao extends JdbcDaoImpl<UserExportCustom, Long>
{
#Autowired
BeanPropertyRowMapper<UserExportCustom> userExportCustomRowMapper;
#Transactional(readOnly = true, timeout = 1)
public List<UserExportCustom> findByExportFlag(Integer exportFlag, String query)
{
List<UserExportCustom> userExportCustomList = null;
try
{
SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("exportFlag", exportFlag, Types.INTEGER);
userExportCustomList = namedParameterJdbcTemplate.query(query, namedParameters,userExportCustomRowMapper);
}
catch (Exception e)
{
e.printStackTrace();
log.error("Error in findByExportFlag: \n" + e);
}
return userExportCustomList;
}
}
public class JdbcDaoImpl<T, ID> implements JdbcDao<T, ID> {
#Autowired
protected JdbcTemplate jdbcTemplate;
#Autowired
protected NamedParameterJdbcTemplate namedParameterJdbcTemplate;
#Override
public List<T> findAll() {
throw new IllegalStateException();
}
#Override
public T save(T api) {
throw new IllegalStateException();
}
#Override
public T update(T api) {
throw new IllegalStateException();
}
#Override
public T saveOrUpdate(T api) {
throw new IllegalStateException();
}
#Override
public T findOne(String unique) {
throw new IllegalStateException();
}
#Override
public T findOneById(ID id) {
throw new IllegalStateException();
}
#Override
public void delete(ID id) {
throw new IllegalStateException();
}
}
If query take more than 1 second than it should give timeout exception but it does not.
try{}catch{} will lead #Transactional to fail ,remove try catch

How to use Spring boot AutoWired and ScheduledExecutorService?

I need to use autowired in more than one class with ScheduledExecutorService, what I have tried is shown in this code. logging size of User list in below example always shows 0, even after user added to arraylist. How to properly use Autowired and ScheduledExecutorService in spring boot?
#Component
public class AnotherClass {
List<User> users = new ArrayList();
public void addUser(User user){
users.add(user);
}
public void logUsers(){
logger.info("User size " + users.size()); <================= Always logs 0, when called from executor
}
}
#RestController
public class SecondClass {
#Autowired
private AnotherClass anotherClass;
#GetMapping(value="/user/test")
public void logUsers(){
anotherClass.addUser(new User());
}
}
Application Class
#Component
#SpringBootApplication
public class SpringBootDemoApplication {
private ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
#Autowired
private AnotherClass anotherClass;
#PostConstruct
public void init() {
logger();
}
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
public void logger(){
exec.scheduleAtFixedRate(new Runnable(){
#Override
public void run(){
try {
anotherClass.logUsers();
}catch (Exception e){
}
}
}, 2000, 1000, TimeUnit.MILLISECONDS);
}
}
The code works if you use the Spring #Autowired and not the #AutoWired Annotation.

converting completeable future

I'm new on completeable-future field. Anyway I have this basic JPA application I want to use async call. But I don't want the service return into completable future.
This one works fine, but..
#Async
#Cacheable(value="distributors")
public CompletableFuture<Iterable<Distributors>> getAllDistributorsAsyncCaching() throws ExecutionException, InterruptedException {
Iterable<Distributors> result = distributorsRepository.findAll();
return CompletableFuture.completedFuture(result);
}
What I want the function to return just the iterable:
#Async
#Cacheable(value="distributors")
public Iterable<Distributors> getAllDistributorsAsyncCaching() throws ExecutionException, InterruptedException {
Iterable<Distributors> result = distributorsRepository.findAll();
return CompletableFuture.completedFuture(result);
}
I have tried with completeablefuture.get() but the problem is it becomes slow,
then I tried with completeablefuture.complete() it gives me complete(Iterable) in CompleteableFuture cannot be applied to ().
Thanks in advance!
You can put #Async on your repository method :
public interface FooRepository extends JpaRepository<Foo, Long> {
#Async
#Query("select f from Foo f")
CompletableFuture<List<Foo>> findAllFoos();
}
Then in your service you call it with :
#Service
public class FooService {
#Autowired
private FooRepository fooRepository;
public List<Foo> getFoos() {
CompletableFuture<List<Foo>> futureFoos = fooRepository.findAllFoos();
List<Foo> foos = null;
try {
foos = futureFoos.get();
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return foos;
}
}
Here is my test (i use h2 in-memory database) :
#RunWith(SpringRunner.class)
#SpringBootTest
public class FooTests {
#Autowired
private FooRepository fooRepository;
#Autowired
private FooService fooService;
#Before
public void setUp() {
for (int i = 0; i < 100000; i++) {
Foo foo = new Foo();
foo.setId(Long.valueOf(i));
foo.setName("foo" + i);
fooRepository.save(foo);
}
}
#Test
public void test() {
System.out.println(fooService.getFoos().size());
}
}
You can put #Cacheable on service method (here is getFoos)

MongoTemplate null pointer exception in class

I have been looking at other answers but none of the seem to work for me, I have a spring boot application where I am using mongo and kafka. In the main class where my run() method is I am able to #Autowired mongoTemplate and it works but then in another class I did the same and I am getting a null pointer exception on the mongoTemplate.
Here are both classes:
Working
#SpringBootApplication
public class ProducerConsumerApplication implements CommandLineRunner {
public static Logger logger = LoggerFactory.getLogger(ProducerConsumerApplication.class);
public static void main(String[] args) {
SpringApplication.run(ProducerConsumerApplication.class, args).close();
}
#Autowired
private Sender sender;
#Autowired
MongoTemplate mongoTemplate;
#Override
public void run(String... strings) throws Exception {
Message msg = new Message();
msg.setCurrentNode("my_node");
msg.setStartTime(System.currentTimeMillis());
String json = "{ \"color\" : \"Orange\", \"type\" : \"BMW\" }";
ObjectMapper objectMapper = new ObjectMapper();
msg.setTest(objectMapper.readValue(json, new TypeReference<Map<String,Object>>(){}));
sender.send(msg);
mongoTemplate.createCollection("test123");
mongoTemplate.dropCollection("test123");
}
Not working
#Component
public class ParentNode extends Node{
#Autowired
public MongoTemplate mongoTemplate;
public void execute(Message message) {
try{
// GET WORKFLOWS COLLECTION
MongoCollection<Document> collection = mongoTemplate.getCollection("workflows");
} catch(Exception e){
e.printStackTrace();
}
}
}
Thank you for the help. It is much appreciated.
can you try to inject dependency with setter or constructor:
Method 1:
#Component
public class ParentNode extends Node{
#Autowired
public ParentNode(MongoTemplate mongoTemplate){
this.mongoTemplate = mongoTemplate;
}
private final MongoTemplate mongoTemplate;
public void execute(Message message) {
try{
// GET WORKFLOWS COLLECTION
MongoCollection<Document> collection = mongoTemplate.getCollection("workflows");
} catch(Exception e){
e.printStackTrace();
}
}
Method 2:
#Component
public class ParentNode extends Node{
#Autowired
public void setMongoTemplate(MongoTemplate mongoTemplate){
ParentNode.mongoTemplate = mongoTemplate;
}
static private MongoTemplate mongoTemplate;
public void execute(Message message) {
try{
// GET WORKFLOWS COLLECTION
MongoCollection<Document> collection = mongoTemplate.getCollection("workflows");
} catch(Exception e){
e.printStackTrace();
}
}

Logging requests and responses in Spring

I'm trying to implement logging system in a Spring boot application. There are requests coming into the system which have one or more responses.
Requests and responses must be logged into the database in a separate thread, not in the worker thread.
This is my idea.
tables in mysql - "request" with required columns, and "response" with request_id as foreign key
relation between resquest and response - one to many.
A separate thread in LogService is started in #PostContruct to save the data in the DB.
I'm sure there are better solutions to this problem. Please guide with some suggestions.
#Service
public class LogServiceImpl implements LogService {
private final BlockingQueue<Object> logQueue = new LinkedBlockingQueue<>();
private volatile boolean done;
// repositories
#Autowired
private RequestRepository requestRepository;
#Autowired
private ResponseRepository responseRepository;
#Async
#Override
public void log(Object obj) {
try {
logQueue.put(obj);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
#PostContruct
private saveToDb(){
new Thread(() -> {
while(!done){
String object = logQueue.poll(5, TimeUnit.SECONDS)
if(object != null){
if(object instanceof Request){
requestRepository.save((Request)object);
}
if(object instanceof Response){
responseRepository.save((Response)object);
}
}
}
}).start();
}
public void stop() {
done = true;
}
}
class Request{
.....
}
class Response{
......
}
#Service
public class SomeService1 {
#Autowired
private LogService logService;
public void someMeth1(Request request) {
....
logService.log(request);
}
}
#Service
public class SomeService2 {
#Autowired
private LogService logService;
public void someMeth2(Response response) {
....
logService.log(response);
}
}

Resources