spring circular reference

while spring framework is discouraging use of filed injection, and in preference of constructor injection for example. There is an issue with circular reference.

For example:

class BeanA{
    @Autowired
    public BeanA(BeanB beanB) {
        this.beanB= beanB;
    }
}

class BeanB{
    @Autowired
    public BeanB(BeanA beanA) {
        this.beanA= beanA;
    }

Field injection would otherwise work. However, with above constructor injection, spring would throw out

APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

┌─────┐
|  beanA defined in URL [jar:file:/...class]
↑     ↓
|  beanB defined in URL [jar:file:/....class]
↑     ↓
|  xx (field xx) 

The alternative solution if must use constructor binding is to use lazy annotation

class BeanA{
    @Autowired
    public BeanA(@Lazy BeanB beanB) {
        this.beanB= beanB;
    }
}

https://github.com/spring-projects/spring-framework/issues/26703

increment and decrement operator

there is an interesting result for this operation

slotCount.computeIfPresent(indice, (k,v) -> v--);

it supposed to reduce the value by one for corresponding indice as the key.

however, the result is `the value is never changed`.

it’s a good reminder, as it happens, the incremental operator is conducting two operations. And the increment/decrement is after the first operation (return the value here) is done.

so the solution is



slotCount.computeIfPresent(indice, (k,v) -> v-1);//return -1 result


slotCount.computeIfPresent(indice, (k,v) -> --v);//minus one, then return



update symbolic link

the command to update the symbolic link is trivial,

ln -sf newPath link

`-f` basically force the overwrite if the link is already existing.

however, the caveat is if the link is pointing to a folder, `-n` is also needed, otherwise it will create a symbolic link to the newPath inside link.



ln -sfn newPath link

even further, even if -n is used, however, if there is `/` after the link (tab completion would do that), the newPath would still be symbolinked into link as a subfolder.


## this won't work
ln -sfn newPath link/  

java parallel stream splitter

Further to the issue with default JDK implementation with IteratorSpliterator, https://lwpro2.dev/2020/12/21/files-list-parallel-stream/

I have created a custom Spliterator to evenly split the stream and with threshold for the split size.

public class CacheSplitter<T> implements Spliterator<T> {
//    private final Collection<T> collection;
    private final T[] values;
    private int start;
    private int end;
    private final int THRESHOLD;
    public CacheSplitter(T[] values, int threshold) {
        this(values, 0, values.length, threshold);
    }
    public CacheSplitter(T[] values, int start, int end, int threshold) {
        this.values = values;
        this.start = start;
        this.end = end;
        this.THRESHOLD = threshold;
    }

    @Override
    public boolean tryAdvance(Consumer action) {
        if(start< end){
            action.accept(values[start++]);
            return true;
        }
        return false;
    }

    @Override
    public Spliterator trySplit() {
        if(end - start < THRESHOLD){
            return null;
        }
        int mid = (start + end)/2;
        return new CacheSplitter(values, start, start= mid+1, THRESHOLD);
    }

    @Override
    public long estimateSize() {
        return end - start;
    }

    @Override
    public int characteristics() {
        return ORDERED | SIZED | SUBSIZED | NONNULL;
    }
}

https://github.com/1wpro2/jdk-patch/blob/main/FixedSizeSpliterator.java

git blame

git blame would give the last commit on all lines. however, there are times it’s really needed is what are the commits for certain one line of code, git log would work out here

git log -S"private List<LocalDate> ...;" src/main/java/...java

git merge preview

it doesn’t come as exact a preview for merge results. however, it does come close, and most importantly tell any new commits on the other branch since the current branch and the other branch diverge

git diff ...the_other_branch

spring abstract class

the modern spring framework has now been able to DI for abstract class properties.

For example:

public abstract class AbstractCacheReader<T extends AbstractMessage> implements ModelCacheReader<T> {

    T models;

    @Value("${....cache.deployment.directory}")
    protected String CACHE_DEPLOYMENT_DIRECTORY;
....
}

with concrete class

@Component
@Slf4j
@Setter
public class ABCCacheReader extends AbstractCacheReader<ABC.ABCModels> implements ModelCacheReader<ABC.ABCModels> {

    public ABCCacheReader() {
..
        models = ABC.ABCModels.newBuilder().build();
    }
....
}

the CACHE_DEPLOYMENT_DIRECTORY would be properly wired onto

ABCCacherReader bean.

protobuf operation

quite impressed by protobuf performance, that the built in implementation is even better than streaming earlier:

models.toBuilder().clear().mergeFrom(
                Files.list(..).filter(Files::isRegularFile)
                        .map(Path::toFile)
                        .filter(file -> ...)
                        .collect(Collectors.toList())
                        .parallelStream()
                        .map(file -> ..)
//read into protobuf
                        .reduce((m1, m2) -> m1.toBuilder().mergeFrom(m2).build())
                        .orElseGet(()-> Stress.StressModels.getDefaultInstance())
            ).build();

models.getModelsList().parallelStream().forEach(...)

is even better performing than

models = Files.list(Paths.get(..)).filter(Files::isRegularFile)
                    .map(Path::toFile)
                    .filter(file -> ..)
                    .collect(Collectors.toList())
                    .parallelStream()
                    .map(file -> ..)
                    .flatMap(m -> m.getModelsList().stream());

models.parallel().forEach(...)