How to use Stream with Mongo db in spring boot - spring

I want to query large collection in Mongodb and tryin to use Stream com.mongodb.connection.Stream . I am doing this in spring boot using MongoRepository. I get error Type 'com.mongodb.connection.Stream' does not have type parameters for the method Stream<Population> findAllStates(String state);. Not sure what is the Type its complaining.
I have collection Population in the mongodb.
My Repository class is
package com.krk.samplemongodb;
import com.mongodb.connection.Stream;
import org.springframework.data.mongodb.repository.Aggregation;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface PopulationRepository extends MongoRepository<Population, String> {
#Query(value = "{'state' :?0}")
Stream<Population> findAllStates(String state);
List<Population> findAll();
}
Thanks

You should change your import to
import java.util.stream.Stream;
Also, make sure to use at least version 1.7 of Spring Data MongoDB as stated in this answer

Up to #neoczar. Maybe too late but according to the documentation of Spring Data Mongodb the stream should be closed to release the server-side resources (cursor). So you can use try with resources to automatically close cursor.
https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongodb.repositories.queries.aggregation

Related

Spring Boot Integration Test case and check if a method is called

I need to write an Integration Test case . In the whole flow i do have a bean class which has a method. I want to write a test case case to check if that method was called in the test or not.
How can i do that ? Any Suggestions ?
You can use the appropriate methods in Mockito
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
verify(mockObject, atLeast(2)).someMethod("was called at least twice");
verify(mockObject, times(1)).someMethod("was called exactly one time");

How does spring boot #Value("${somevalue}") annotation work?

I have some #Value annotation in spring-boot project. To Simplify, I have few classes: a restcontroller, service (annotated with #Service) and a pojo.
In each of these classes, I declared a variable as below:
#Value("${somevalue}")
private String somevalueVariable
In the controller class, the value is getting populated as defined in the application.properties. So no problem here.
In the service class, the value is showing up as null. This is my issue, how should i fix it to get the value from the application.properties
In the pojo, the value is showing up as null, I am thinking this is expected behaviour as spring does not manage this class.
Try this:
import org.springframework.beans.factory.annotation.Value;
#Value("#{${somevalue}}")
private String somevalueVariable
ideally service class should have #Service anotation over it, either you missed that or this class is not scanned by spring context, so please add ComponentScan anotation for service class package over main class to scan classes uner this package -
#SpringBootApplication
#ComponentScan({"com.in28minutes.springboot"})
public class Application
It uses Spring Expression Language (SpEL):
https://docs.spring.io/spring-integration/docs/5.3.0.RELEASE/reference/html/spel.html
Also there is 2 #Value : org.springframework.beans.factory.annotation.Value and lombok.Value;
Make sure you are using the right one.
To get value from property try this:
#Value("${systemValue}")
private String systemValue;
For more information I find this useful:
https://www.baeldung.com/spring-value-annotation

How to declare a GORM domain class without Grails?

I'm making a project on Groovy + Spring using GORM, without implementing Grails. In order to do so, I'm following the guide that Grails provide (http://guides.grails.org/gorm-without-grails/guide/index.html). And even when I have the same Domains As them, when I run it and it bootstraps the data, it throws an exception saying that
Either class [domains.Manufacturer] is not a domain class or GORM has
not been initialized correctly or has already been shutdown. Ensure
GORM is loaded and configured correctly before calling any methods on
a GORM entity.
and this is my Manufacter.groovy file:
import grails.gorm.annotation.Entity
import groovy.transform.ToString
import org.grails.datastore.gorm.GormEntity
#ToString
#Entity
class Manufacturer implements GormEntity<Manufacturer> {
String name
static hasMany = [vehicles: Vehicle]
static constraints = {
name blank: false
}
}
Any idea of why this error happens even though I have followed the exact same steps as them? Does it has something to do with dependencies version?
Thank you very much in advance

#Reference from Servlet Filter

I am writing a Servlet Filter and would like to use one of my Liferay components using #Reference:
package my.filter;
import my.Compo;
import org.osgi.service.component.annotations.Reference;
public class MyFilter implements Filter {
#Override
public void doFilter(...) {
compo.doTheThing();
}
#Reference(unbind = "-")
protected my.Compo compo;
}
I get this Java compilation error:
annotation type not applicable to this kind of declaration
What am I doing wrong?
Is it maybe impossible to achieve this?
As tipped by Miroslav, #Reference can only be used in an OSGi component, and a servlet filter is not one.
The solution in Liferay 7 is to develop a filter component.
The procedure to do so is explained at http://www.javasavvy.com/liferay-dxp-filter-tutorial/
You can make a simple filer like: https://www.e-systems.tech/blog/-/blogs/filters-in-liferay-7 and http://www.javasavvy.com/liferay-dxp-filter-tutorial/
But you can also use regular filters, as long you configure you Liferay webapp for that -> there are two consequences if you use regular filters though: you will be out of osgi application and you will have to keep track of this whenever you update your bundle. That is why you should not go with regular implementation. (just complementing the OP answer with the underlining reason to avoid the initial track)

Hibernate interceptor or listener with Spring Boot and Spring Data JPA

I'd like to run some checks prior to saving a collection of children of an object (cascade = all).
I am using Spring Boot and Spring Data JPA and was wondering what approach would be the best: a Hibernate listener or an interceptor. What are the pros/cons of each ? Do you happen to have an example for the one you consider the best approach ?
I have used Hibernate listeners before configured in XML like this:
<property name="eventListeners">
<map>
<entry key="post-update">
<list>
<ref bean="myListener" />
</list>
</entry>
</map>
</property>
on the session factory (older project). But now most of my configs are in annotations (cause Spring Boot) and I want to keep the configs as simple and light as possible, so maybe an interceptor would be a better solution.
Thank you.
I did a lot of looking around on this for myself and thought I'd share what I got working (I included the helpful (non-inline) links at the bottom).
Interceptor
To use an interceptor, you extend the org.hibernate.EmptyInterceptor class and override the methods you want to intercept.
You probably want onSave(...) in your case.
package foo.bar;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;
import java.io.Serializable;
public class MyInterceptor extends EmptyInterceptor {
#Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
// do your checks here
return false;
}
}
You have to register your interceptor with Spring/Hibernate.
You can do this in your application.properties or application.yml.
spring:
jpa:
properties:
hibernate.ejb.interceptor: foo.bar.MyInterceptor
The upsides to an interceptor are that it is (potentially) less code and relatively simple configuration.
The downsides are that you can only have one for your entire application and the API can be confusing to work with.
Event Listener
For events, you implement one of Hibernate's org.hibernate.event.spi.*Listener interfaces.
You probably want the org.hibernate.event.spi.PreInsertEventListener in your case.
You have to register your event in the EventListenerRegistry.
To do this, you can make your class a #Component, #Autowire the EntityManagerFactory into your class, and create a #PostConstruct method to register your class.
package foo.bar;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PreInsertEvent;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.internal.SessionFactoryImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManagerFactory;
#Component
public class MyEventListener implements PreInsertEventListener {
#Autowired
private EntityManagerFactory entityManagerFactory;
#PostConstruct
private void init() {
SessionFactoryImpl sessionFactory = entityManagerFactory.unwrap(SessionFactoryImpl.class);
EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.PRE_INSERT).appendListener(this);
}
#Override
public boolean onPreInsert(PreInsertEvent preInsertEvent) {
// do your checks here
return false;
}
}
The upsides to listeners are that you can have as many as you want, the API is nicer than the interceptor's, and the code and the configuration are all in one place.
The downside is that the configuration is longer and more involved.
https://docs.jboss.org/hibernate/orm/3.5/reference/en-US/html/events.html
How to use Spring managed Hibernate interceptors in Spring Boot?
https://dzone.com/articles/spring-managed-hibernate-event-listeners
Hello,
First of all you can check the: https://www.baeldung.com/database-auditing-jpa where every options is explained in detail.
I would personally recommend Hibernate Interceptor, easy to use and understand. Depending on the complexity of the project, in most cases it will do.
In order to configure this in your application you simply need to add: spring.jpa.properties.hibernate.ejb.interceptor = path.to.interceptor (in application.properties). The interceptor itself should be #Component.
As long as the interceptor doesn't actually use any beans. Otherwise it is a bit more complicated but I would be more than happy to offer the solution.
Don't forget to add in application-test.properties, an EmptyInterceptor to not use the logging system (or whatever you want to use it for) in tests (which wouldn't be very helpful).
Hope this was of use to you.
As a final note: always update your Spring / Hibernate versions (use the latest as possible) and you will see that most code will become redundant as newer versions try to reduce the configurations as much as possible.

Resources