Walk all results using a Spring Data and pagination - spring

I'm calling a paginate service
I can walk all the paginated collection using code like this:
Pageable pageable = PageRequest.of(0,100);
Page<Event> events = eventsService.getEventsPage(pageable);
while(!events.isLast()) {
doStuff(events)
events = eventsService.getEventsPage(events.nextPageable())
}
doStuff(events) // rest of events
is there a more elegant solution?. I need the pagination because otherwise, the system will run out of memory.

I'd use the getContent() from Slice (which is inherited by Page).
List <T> getContent()
Returns the page content as List.
Pageable pageable = PageRequest.of(0,100);
Page<Event> events = eventsService.getEventsPage(pageable);
List<Event> eventList = events.getContent();
for (Event event : eventList) {
// do stuff
}

I feel like having to state the service call and doStuff twice is somehow fragile. You can utilze the fact that nextPageable() will give you the unpaged singleton if the current page is the last one already.
Pageable pageable = PageRequest.of(0,100);
do {
Page<Event> events = eventsService.getEventsPage(pageable);
doStuff(events)
pageable = events.nextPageable();
} while(pageable.isPaged())
Here is the doc of nextPageable().
/**
* Returns the {#link Pageable} to request the next {#link Slice}. Can be {#link Pageable#unpaged()} in case the
* current {#link Slice} is already the last one. Clients should check {#link #hasNext()} before calling this method.
*
* #return
* #see #nextOrLastPageable()
*/
Pageable nextPageable();
Pageable#unpaged() will return a singleton that returns false for isPaged().

Related

How can I cache a database query with "IN" operator?

I'm using Spring Boot with Spring Cache. I have a method that, given a list of ids, returns a list of Food that match with those ids:
public List<Food> get(List<Integer> ids) {
return "select * from FOOD where FOOD_ID in ids"; // << pseudo-code
}
I want to cache the results by id. Imagine that I do:
List<Food> foods = get(asList(1, 5, 7));
and then:
List<Food> foods = get(asList(1, 5));
I want to Food with id 1 and Food with id 5 to be retrieved from cache. Is it possible?
I know I can do a method like:
#Cacheable(key = "id")
public Food getById(id){
...
}
and iterate the ids list and call it each time, but in that case I don't take advantage of IN SQL operator, right? Thanks.
The key attribute of Cacheable takes a SpEL expression to calculate the cache key. So you should be able to do something like
#Cacheable(key = "#ids.stream().map(b -> Integer.toString(b)).collect(Collectors.joining(",")))
This would require the ids to always be in the same order
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html#cache-annotations-cacheable-key
A better option would be to create a class to wrap around your ids that would be able to generate the cache key for you, or some kind of utility class function.
Another possible Solution without #Cacheable would be to inject the cache manager into the class like:
#Autowired
private CacheManager cacheManager;
You can then retrieve the food cache from the cache manager by name
Cache cache = cacheManager.getCache('cache name');
then you could adjust your method to take in the list of ids and manually add and get the values from cache
cache.get(id);
cache.put(id, food);
You will most likely still not be able to use the SQL IN clause, but you are at least handling the iteration inside the method and not everywhere this method is called, and leveraging the cache whenever possible.
public List<Food> get(List<Integer> ids) {
List<Food> result = new ArrayList<>();
for(Integer id : ids) {
// Attempt to fetch from cache
Food food = cache.get(id);
if (food == null) {
// Fetch from DB
cache.put(id, food);
}
result.add(food);
}
return result;
}
Relevant Javadocs:
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/CacheManager.html
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/Cache.html

Open / Closed Principle & Single Responsibilty -- Graphs

I am coding a Graph exploration program and have hit a bit of a stumbling block.
My graph is made up of Vertex and NetworkLink objects, and can be obatined by querying a GeographyModel object.
The idea is List<NetworkLink> is retrieved from the GeographyModel and then supplied to a MetaMap to get the required additional information.
What I want to do is try and adhere to the Open / Closed Principle by adding information each NetworkLink by creating MetaMap objects, but have somewhat got my knickers in a twist as to how to do this!
Below is the code for the MetaMap.
public class MetaMap<T> {
private final String name;
private final Map<NetworkLink, List<T>> metaData;
private final Map<T, Set<NetworkLink>> reverseLookup;
private final List<T> fallback;
private final List<T> information;
public MetaMap(String name, T fallback){
this.name = name;
this.metaData = new HashMap<>();
this.reverseLookup = new HashMap<>();
this.fallback = new ArrayList<>();
this.fallback.add(fallback);
this.information = new ArrayList<>();
}
/**
* Returns an identifier giving the information contained in this map
*
* #return
*/
public String getName() {
return name;
}
/**
* Marks from origin to destination with information of type T
*
* #param line
* #param information
*/
public void markLineFragment(RunningLine line, T information) {
line.getLinks().stream().map((link) -> {
if(!metaData.containsKey(link)) {
metaData.put(link, new ArrayList<>());
}
return link;
}).forEach((link) -> {
metaData.get(link).add(information);
});
if(!reverseLookup.containsKey(information)) {
reverseLookup.put(information, new HashSet<>());
}
reverseLookup.get(information).addAll(line.getLinks());
}
/**
* Returns the information on the given NetworkLink
*
* #param link
* #return
*/
public List<T> getInformation(NetworkLink link) {
return metaData.getOrDefault(link, fallback);
}
/**
* Returns the information associated with the given line fragment
* #param line
* #return
*/
public List<T> getInformation(RunningLine line) {
Set<T> resultSet = new HashSet();
line.getLinks().stream().forEach((link) -> {
List<T> result = getInformation(link);
resultSet.addAll(result);
});
return new ArrayList<>(resultSet);
}
/**
* Returns all of the matching links which match the given information
* #param information
* #return
*/
public List<NetworkLink> getMatchingLinks(T information) {
return new ArrayList<>(reverseLookup.get(information));
}
public void addInformation(T info) {
information.add(info);
}
public void removeInformation(T info) {
information.remove(info);
}
Now... the problem I have is that as I expand the program, each new part will require a new MetaMap which is derived from GeographyModel.
I want to follow the OCP and SRP as I am adding capabilities the program, but get a touch stuck as to implementation / combining the two concepts. A couple of thoughts do occur...
I could get each new model requiring a MetaMap to register itself with the GeographyModel, but fear I would be violating the SRP. Each new prgoram feature could own a MetaMap and maintain it, but that would require querying the GeographyModel in the first place.
Any ideas how I could approach this?
Why would you want to implement OCP? What problems are you trying to solve?
If you implemented OCP only because of everyone else thought it was good I strongly recommend you to think twice.
Each principle in SOLID / GRASP as well as design patterns are guild-lines and solutions for a very specific kind of problems. Basically they are tools. You should identify your problems first, state them as clearly as possible. They you will be able to pick the right tools to deal with them.
Blindly implementing SOLID / GRASP or design patterns is much like using a hammer for cooking food. If you were lucky enough you might success but we both know that the probability was very low.
https://www.u-cursos.cl/usuario/777719ab2ddbbdb16d99df29431d3036/mi_blog/r/head_first_design_patterns.pdf
Please navigate to page 125/681 (on the top bar) and read the entire page!

LDAP template search by multiple attributes

Trying to search for users details by using userid,emailid,firstname,lastname,GUID,etc...many more values that need to be added in future
The search should be performed using all the attributes which are not null.
Found this piece of code online *
String filter = "(&(sn=YourName)(mail=*))";
*
Is there any other predefined template or such to do the search, more optimal way without directly specifying values to be Null or using if else statements for each and every attribute? All values must be passed to the method and those not null must be used for search using LDAP. Anything? Please help.
You can effectively use the Filters at run time to specify what to use for search and what not depending on some rules or your NULL validations on attributes. Pls find sample code which fetches person name using filters in ldapTemplate :-
public static final String BASE_DN = "dc=xxx,dc=yyy";
private LdapTemplate ldapTemplate ;
public List getPersonNames() {
String cn = "phil more";
String sn = "more";
AndFilter filter = new AndFilter();
filter.and(new EqualsFilter("objectclass", "person"));
filter.and(new EqualsFilter("sn", sn));
filter.and(new WhitespaceWildcardsFilter("cn", cn));
return ldapTemplate.search(
BASE_DN,
filter.encode(),
new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs)
throws NamingException {
return attrs.get("cn").get();
}
});
}
As name suggests the AndFilters joins all individual filters used in lookup like EqualFilter which checks for equality of attributes while WhitespaceWildcardsFilter to perform wildcard search. So here like we got cn = phil more, it in turn uses *phil*more* for search.

Vaadin: how to avoid cascade valuechange events between fields

I have several fields in a screen, that are partially dependent each on other by validating rules.
If user changes one field then I can affect another fields using setValue(). But I am fighting with the problem, valueChange event is fired from setValue() just as from user activity.
My example: I have four fields "activity_status", "schedule_date", "start_date", "end_date". By editing any one field I want to affect another three fields (changing status, setting or shifting dates). How to avoid recursive calling valueChange method?
I can imagine a variable justProcessedField that can working as a lock, but has anybody a better hands-on solution?
Usually we do set a flag when we trigger the first valueChangeEvent() and then ignore all others, until the first trigger is finished processing.
The pseudocode looks like this:
private boolean _ignoreTriggers= false; // Set ignore triggers when we do manual setValue stuff
field1.addListener(new ValueChangeListener() {
#Override
public void valueChange(ValueChangeEvent event) {
if (!_ignoreTriggers) {
_ignoreTriggers= true;
// Do the processing and setValues(...) in the other fields
_ignoreTriggers= false;
}
}
}
);
With different booleans you can also make groups of fields "sensisble/insensible" to changes in other fields.
To avoid the ValueChangeEvents you can create custom fields, which are extentions of the fields you want to modify. This custom fields should have a public method which calls the setInternalValue method.
Example for Checkbox-Field:
public class CheckBoxSilent extends CheckBox {
/**
* Set the new value without calling a {#link ValueChangeListener}
*
* #param newValue the new value to be set.
*/
public void setValueSecretly(boolean newValue) {
setInternalValue(newValue);
markAsDirty();
}
}

Is there a function like _compile_select or get_compiled_select()?

Looks like _compile_select is deprecated and get_compiled_select is not added to 2.1.0. Are there any other functions like those two? And also I am curious. Is there any particular reason to not adding get_compiled_select() to Active Record and removing _compile_select?
I've added get_compiled_select() to DB_active_rec.php and it seems to work without problem, but i wouldn't remove _compile_select() since it's used in many other methods.
The pull request for adding this method is here, with some other useful methods like:
get_compiled_select()
get_compiled_insert()
get_compiled_update()
get_compiled_delete()
https://github.com/EllisLab/CodeIgniter/pull/307
if you want just the method, it's just this:
/**
* Get SELECT query string
*
* Compiles a SELECT query string and returns the sql.
*
* #access public
* #param string the table name to select from (optional)
* #param boolean TRUE: resets AR values; FALSE: leave AR vaules alone
* #return string
*/
public function get_compiled_select($table = '', $reset = TRUE)
{
if ($table != '')
{
$this->_track_aliases($table);
$this->from($table);
}
$select = $this->_compile_select();
if ($reset === TRUE)
{
$this->_reset_select();
}
return $select;
}

Resources