Making Generic Class Using Lambda Expression - java

I have the below Service class which implement retry mechanism :
#RequiredArgsConstructor(onConstructor_ = {#Autowired})
#Service
public class RetryService {
private final RetryTemplate vcRetry;
private final Order1dao order1;
private final Order2dao order2;
public void saveOrder1(OrderRecord1 record) {
vcRetry.execute(
context -> {
order1.save(record);
});
}
public OrderRecord2 UpdateOrder2(OrderRecord2 record) {
return vcRetry.execute(
context -> {
return order2.Update(record);
});
}
public void saveOrder2(OrderRecord2 record) {
vcRetry.execute(
context -> {
order2.save(record);
});
}
There can be many daoBean which may uses the same RetryService class so i need to write the separate function for the individual bean.
Main Class:
public class OrderProcessor {
private final RetryService retryService;
public void SaveOrder(Order1 x, Order2 y,....) {
retryService.saveOrder1(x);
retryService.saveOrder2(y);
retryService.Update(y);
}
}
How can I make my RetryService class generic ?

You can create a GenericDao and use it in RetryService as below,
class GenericDao<T>{
//dao operations
}
class RetryService<T1 , T2> {
private final RetryTemplate vcRetry;
private final GenericDao<T1> order1;
private final GenericDao<T2> order2;
public void saveOrder1(T1 record) {
vcRetry.execute(
context -> {
order1.save(record);
});
}
public T2 UpdateOrder2(T2 record) {
return vcRetry.execute(
context -> {
return order2.Update(record);
});
}
public void saveOrder2(T2 record) {
vcRetry.execute(
context -> {
order2.save(record);
});
}
}
I hope it helps!

Related

Better solution to call method from interface in every service

I would like to create service which searching and returns objects from repositories, so:
I created interface which has method:
public interface ShapeServicesInterface {
List<ShapeEntity> getAll();
String getName();
}
and few services which implements that interface:
#Service
#RequiredArgsConstructor
public class CircleEntityService implements ShapeServicesInterface {
private final CircleEntityRepository circleEntityRepository;
#Override
public List<ShapeEntity> getAll() {
return new ArrayList<>(circleEntityRepository.findAll());
}
#Override
public String getName() {
return "circle";
}
}
and second one:
#Service
#RequiredArgsConstructor
public class SquareEntityService implements ShapeServicesInterface {
private final SquareEntityRepository squareEntityRepository;
#Override
public List<ShapeEntity> getAll() {
return new ArrayList<>(squareEntityRepository.findAll());
}
#Override
public String getName() {
return "square";
}
}
and next in other service I would like to call that method for getting all entites from that repositories (entites extend abstract class ShapeEntity) - found solution like that:
#Service
#RequiredArgsConstructor
public class TestService {
private final ShapeServiceFacade facade;
private final ExecutorService executorService;
public List<ShapeEntity> getAll() throws ExecutionException, InterruptedException {
List<ShapeEntity> allShapes = new ArrayList<>();
List<Future<List<ShapeEntity>>> futures = new ArrayList<>();
for (ShapeServicesInterface shapeDownloader : facade.getServices()) {
futures.add(executorService.submit(new ShapeTask(shapeDownloader)));
}
for (Future<List<ShapeEntity>> future : futures) {
allShapes.addAll(future.get());
}
return allShapes;
}
ShapeTask is:
#RequiredArgsConstructor
private static class ShapeTask implements Callable<List<ShapeEntity>> {
private final ShapeServicesInterface servicesInterface;
#Override
public List<ShapeEntity> call() {
return servicesInterface.getAll();
}
}
Facade is:
#Service
public class ShapeServiceFacade {
private final Map<String, ShapeServicesInterface> shapeServices;
public ShapeServiceFacade(Set<ShapeServicesInterface> allServices) {
this.shapeServices = allServices.stream()
.collect(Collectors.toMap(ShapeServicesInterface::getName,Function.identity()));
}
public List<ShapeServicesInterface> getServices() {
return new ArrayList<>(shapeServices.values());
}
}
but it is a little complicated. Is there a easier way to call that methods? I would like to add more methods so I will have to implement another task and another method in service, and in interface. I care about searching in every repostiory.
Maybe the ShapeServiceFacade can be omitted, if you are using spring boot, like that
#Service
#RequiredArgsConstructor
public class TestService {
#Autowired
private final List<ShapeServicesInterface> serviceList;
private final ExecutorService executorService;
public List<ShapeEntity> getAll() throws ExecutionException, InterruptedException {
List<ShapeEntity> allShapes = new ArrayList<>();
List<Future<List<ShapeEntity>>> futures = new ArrayList<>();
for (ShapeServicesInterface shapeDownloader : serviceList) {
futures.add(executorService.submit(new ShapeTask(shapeDownloader)));
}
for (Future<List<ShapeEntity>> future : futures) {
allShapes.addAll(future.get());
}
return allShapes;
}

Issue in making Consumer Listener aware of seeking from beginning

I am not able to understand design of SeekAware interfaces.
I am trying to implement dynamic listeners to the new topic created from spring-kafka rest api.As of now only consumes consumer records from the time the listener started on topic but also wanted to modify offsets on start of this listener so that if want to seekToBeginning, my listener whenever invoked will read from start of topic.
the bits and pieces of important code are as follows
#Component
public class CustomKafkaListenerRegistrar implements InitializingBean {
#Autowired
private KafkaListenerEndpointRegistry kafkaListenerEndpointRegistry;
#Autowired
private KafkaListenerContainerFactory kafkaListenerContainerFactory;
public void registerCustomKafkaListener(String name, CustomKafkaListenerProperty customKafkaListenerProperty,
boolean startImmediately) {
String listenerClass = String.join(".", CustomKafkaListenerRegistrar.class.getPackage().getName(),
customKafkaListenerProperty.getListenerClass());
CustomMessageListener customMessageListener =
(CustomMessageListener) beanFactory.getBean(Class.forName(listenerClass));
kafkaListenerEndpointRegistry.registerListenerContainer(
customMessageListener.createKafkaListenerEndpoint(name, customKafkaListenerProperty.getTopic()),
kafkaListenerContainerFactory, startImmediately);
}
public abstract class CustomMessageListener {
private static int NUMBER_OF_LISTENERS = 0;
#Autowired
private KafkaProperties kafkaProperties;
public abstract KafkaListenerEndpoint createKafkaListenerEndpoint(String name, String topic);
protected MethodKafkaListenerEndpoint<String, String> createDefaultMethodKafkaListenerEndpoint(String name,
String topic) {
MethodKafkaListenerEndpoint<String, String> kafkaListenerEndpoint = new MethodKafkaListenerEndpoint<>();
kafkaListenerEndpoint.setId(getConsumerId(name));
kafkaListenerEndpoint.setGroupId(kafkaProperties.getConsumer().getGroupId());
kafkaListenerEndpoint.setAutoStartup(true);
kafkaListenerEndpoint.setTopics(topic);
kafkaListenerEndpoint.setMessageHandlerMethodFactory(new DefaultMessageHandlerMethodFactory());
return kafkaListenerEndpoint;
}
private String getConsumerId(String name) {
if (isBlank(name)) {
return CustomMessageListener.class.getCanonicalName() + "#" + NUMBER_OF_LISTENERS++;
} else {
return name;
}
}
private boolean isBlank(String string) {
return Optional.ofNullable(string)
.map(String::isBlank)
.orElse(true);
}
}
#Component
public class MyCustomMessageListener extends CustomMessageListener {
#Override
#SneakyThrows
public KafkaListenerEndpoint createKafkaListenerEndpoint(String name, String topic) {
MethodKafkaListenerEndpoint<String, String> kafkaListenerEndpoint =
createDefaultMethodKafkaListenerEndpoint(name, topic);
kafkaListenerEndpoint.setBean(new MyMessageListener());
kafkaListenerEndpoint.setMethod(MyMessageListener.class.getMethod("onMessage", ConsumerRecord.class));
return kafkaListenerEndpoint;
}
#Slf4j
private static class MyMessageListener implements MessageListener<String, String> {
#Override
public void onMessage(ConsumerRecord<String, String> record) {
log.info("My message listener got a new record: " + record);
log.info("message is: "+record.toString());
CompletableFuture.runAsync(this::sleep)
.join();
log.info("My message listener done processing record: " + record);
}
#SneakyThrows
private void sleep() {
Thread.sleep(5000);
}
}
}
As far as I understood, MyCustomMessageListener will implement the interface ConsumerSeekAware which in turn will provide method seekToBeginning will get invoked on creation and trigering of listener.
Kindly help.
Note: I am using MessageListener<String, String> having method onMessage which as per my knowledge is equivalent to working of #KafkaListener.Kindly correct me if I am wrong.
If you implement MessageListener there is no need for all the KafkaListenerEndpoint stuff; just create a listener container and add your listener to it.
#SpringBootApplication
public class So72546425Application {
public static void main(String[] args) {
SpringApplication.run(So72546425Application.class, args);
}
#Bean
ApplicationRunner runner1(KafkaTemplate<String, String> template) {
return args -> {
template.send("so72546425", "foo");
};
}
#Bean
ApplicationRunner runner2(ContainerCreator creator) {
return args -> {
System.out.println("Hit enter to create a container");
System.in.read();
MessageListenerContainer container = creator.createContainerForTopic("so72546425");
container.start();
};
}
}
#Component
class ContainerCreator {
private final ConcurrentKafkaListenerContainerFactory<String, String> factory;
ContainerCreator(ConcurrentKafkaListenerContainerFactory<String, String> factory) {
this.factory = factory;
}
ConcurrentMessageListenerContainer<String,String> createContainerForTopic(String topic) {
ConcurrentMessageListenerContainer<String, String> container = factory.createContainer(topic);
container.getContainerProperties().setMessageListener(new MyListener());
container.getContainerProperties().setGroupId("group.for." + topic);
return container;
}
}
class MyListener extends AbstractConsumerSeekAware implements MessageListener<String, String> {
#Override
public void onMessage(ConsumerRecord<String, String> data) {
System.out.println(data);
}
#Override
public void onPartitionsAssigned(Map<TopicPartition, Long> assignments, ConsumerSeekCallback callback) {
System.out.println("Seeking to beginning");
callback.seekToBeginning(assignments.keySet());
}
}

How to extract the common condition check in a class

If I have a class, where all methods should evaluate only if a boolean attribute is true, what is the best way to define it in terms of best practices?
Is there a way to replace the recurring isEnabled check in all the methods by a single check? The current form works, I'm looking for a way to improve it to not have isEnabled checked in all the methods.
#Singleton
public class SomeClass implements SomeInterface {
EventPublisher eventPubilsher;
boolean isEnabled;
#Inject
public SomeClass(final Decider decider, EventPublisher, eventPublisher) {
this.isEnabled = decider.isSomethingEnabled();
this.eventPublisher = eventPublisher;
}
#Override
public void method1() {
if(isEnabled){
eventPublisher.publishSomething1();
}
}
#Override
public void method2() {
if(isEnabled){
eventPublisher.publishSomething2();
}
}
#Override
public void method3() {
if(isEnabled){
eventPublisher.publishSomething3();
}
}
}
You can have implementation for enabled stuff, and one for disabled stuff. The disabled implementation won't do anything:
public class DisabledSomeClass implements SomeInterface {
#Override
public void method1() {
}
#Override
public void method2() {
}
#Override
public void method3() {
}
}
Enabled one will publish stuff:
public class EnabledSomeClass implements SomeInterface {
EventPublisher eventPublisher;
public EnabledSomeClass(EventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
#Override
public void method1() {
eventPublisher.publishSomething1();
}
#Override
public void method2() {
eventPublisher.publishSomething2();
}
#Override
public void method3() {
eventPublisher.publishSomething3();
}
}
Then extract the logic, if functionality is enabled in new factory class - SomeInterfaceFactory (probably not the best name, but you get the idea), it will return the correct implementation, depending on whether something is enabled.
public class SomeInterfaceFactory {
public static SomeInterface getInstance(Decider decider, EventPublisher eventPublisher) {
if (decider.isSomethingEnabled()) {
return new EnabledSomeClass(eventPublisher);
} else {
return new DisabledSomeClass();
}
}
}
This should work
#Singleton
public class SomeClass implements SomeInterface {
EventPublisher eventPubilsher;
boolean isEnabled;
#Inject
public SomeClass(final Decider decider, EventPublisher, eventPublisher) {
this.isEnabled = decider.isSomethingEnabled();
this.eventPublisher = eventPublisher;
}
#Override
public void method1() {
publish(ep->ep.publishSomething1());
}
#Override
public void method2() {
publish(ep->ep.publishSomething2());
}
#Override
public void method3() {
publish(ep->ep.publishSomething3());
}
private void publish(Consumer<EventPublisher> callback){
if(isEnabled) callback.accept(eventPublished);
}
}
A Runnable interface can receive a lambda without args and run a lambda function with run() method. So, you can create a method inside your Decider class and receive a Runnable as a parameter, like:
class Decider{
private boolean enabled;
//...
public void execute(Runnable runnable){
if(enabled) runnable.run();
}
}
And receive your Decider and do:
//...
EventPublisher eventPubilsher;
Decider decider;
#Inject
public SomeClass(final Decider decider, EventPublisher, eventPublisher) {
this.decider = decider;
this.eventPublisher = eventPublisher;
}
#Override
public void method1() {
Decider.execute(() -> eventPublisher.publishSomething1());
}
//...
You're locking the evaluation of the condition to the constructor. If you want any flexibility, you should pull it out.
public class SomeClass implements SomeInterface {
boolean isEnabled;
public SomeClass(EventPublisher, eventPublisher) {
//
}
public void addDecide(boolean value){
isEnabled = value;
}
boolean getEnabled(){
return isEnabled;
}
#Override
public void method3() {
if(getEnabled()){
eventPublisher.publishSomething3();
}
}
}
You can even go crazy and add a supplier:
public void addDecide(Supplier<Boolean> supplier){
supplier = supplier;
}
boolean getEnabled(){
return supplier.get();
}

Custom JavaFX events

I have a custom event listener:
public interface IMyCustomListener {
public void onEvent1(int param0);
public void onEvent2(String param0);
}
now I would fire events with javafx events pattern (Event, EventTarget, EventHandler...), how can I do this?
You cannot. JavaFX uses javafx.event.Events or subtypes, so String or even primitive int can't be passed.
You could however create a custom subtype of Event and add the parameters to this class.
Similarly only classes implementing javafx.event.EventHandler can be registered as event handlers.
You could create a event handler class that delegates to your methods though:
public abstract class CustomEvent extends Event {
public static final EventType<CustomEvent> CUSTOM_EVENT_TYPE = new EventType(ANY);
public CustomEvent(EventType<? extends Event> eventType) {
super(eventType);
}
public abstract void invokeHandler(MyCustomEventHandler handler);
}
public class CustomEvent1 extends CustomEvent {
public static final EventType<CustomEvent> CUSTOM_EVENT_TYPE_1 = new EventType(CUSTOM_EVENT_TYPE, "CustomEvent1");
private final int param;
public CustomEvent1(int param) {
super(CUSTOM_EVENT_TYPE_1);
this.param = param;
}
#Override
public void invokeHandler(MyCustomEventHandler handler) {
handler.onEvent1(param);
}
}
public class CustomEvent2 extends CustomEvent {
public static final EventType<CustomEvent> CUSTOM_EVENT_TYPE_2 = new EventType(CUSTOM_EVENT_TYPE, "CustomEvent2");
private final String param;
public CustomEvent2(String param) {
super(CUSTOM_EVENT_TYPE_2);
this.param = param;
}
#Override
public void invokeHandler(MyCustomEventHandler handler) {
handler.onEvent2(param);
}
}
public abstract class MyCustomEventHandler implements EventHandler<CustomEvent> {
public abstract void onEvent1(int param0);
public abstract void onEvent2(String param0);
#Override
public void handle(CustomEvent event) {
event.invokeHandler(this);
}
}
Usage Example
Button btn = new Button("Say 'Hello World'");
btn.setOnAction((ActionEvent event) -> {
btn.fireEvent(new CustomEvent1(42));
btn.fireEvent(new CustomEvent2("Hello World"));
});
btn.addEventHandler(CustomEvent.CUSTOM_EVENT_TYPE, new MyCustomEventHandler() {
#Override
public void onEvent1(int param0) {
System.out.println("integer parameter: " + param0);
}
#Override
public void onEvent2(String param0) {
System.out.println("string parameter: "+param0);
}
});

Strategy pattern with inner enum

I'm trying to get rid of big switch statement from my code and I thought that Strategy pattern based on my existing enum would be nice. The concept is like:
public class MyStrategy {
public MyStrategy() {
Option.Option1.setMethodToExecute(this::action1);
Option.Option2.setMethodToExecute(this::action2);
}
public void executeChoosenMethod(int i) {
Option.values()[i].execute();
// instead of
// switch(convertItoOption()) {
// case Option1:...
// case Option2:...
// }
}
private void action1() {
System.out.println("action1");
}
private void action2() {
System.out.println("action2");
}
private enum Option {
Option1, Option2;
private InvokeAction methodToExecute;
public void setMethodToExecute(InvokeAction methodToExecute) {
this.methodToExecute = methodToExecute;
}
public void execute() {
methodToExecute.execute();
}
}
#FunctionalInterface
private interface InvokeAction {
void execute();
}
}
so I can use it like:
public class StrategyTest {
public static void main(String[] args) {
MyStrategy strategy = new MyStrategy();
//user choose 0 or 1
strategy.executeChoosenMethod(0);
strategy.executeChoosenMethod(1);
}
}
but I don't like this part with Option.Option1.setMethodToExecute(this::action1); since my enum has more and more options and I would like to have all of this inside enum. What would be perfect is something like this:
public class MyStrategy {
public void executeChoosenMethod(int i) {
Option.values()[i].execute();
}
private void action1() {
System.out.println("action1");
}
private void action2() {
System.out.println("action2");
}
private enum Option {
Option1(MyStrategy.this::action1),
Option2(MyStrategy.this::action2);
private InvokeAction methodToExecute;
private Option(InvokeAction method) {
methodToExecute = method;
}
public void execute() {
methodToExecute.execute();
}
}
#FunctionalInterface
private interface InvokeAction {
void execute();
}
}
but this is impossible since enum is static and I don't have access to enclosing instance by MyStrategy.this. I need enum, because I have set of options and it is convenient to use methods like values() or valueOf(), but what I would like to have is single line invoke instead of growing switch.
Do you have any ideas how to achieve sometghing like this or is there any workaround to make this enum constructor call possible Option1(MyStrategy.this::action1) ?
With enums you could implement it like this:
public class MyStrategy {
public void executeChoosenMethod(int i) {
Option.values()[i].execute(this);
}
private void action1() {
System.out.println("action1");
}
private void action2() {
System.out.println("action2");
}
private enum Option {
Option1(MyStrategy::action1),
Option2(MyStrategy::action2);
private InvokeAction methodToExecute;
private Option(InvokeAction method) {
methodToExecute = method;
}
public void execute(MyStrategy s) {
methodToExecute.execute(s);
}
}
#FunctionalInterface
private interface InvokeAction {
void execute(MyStrategy s);
}
}
This uses the fact the with lambdas you can make method references to arbitrary instance methods and call them on a specific instance by passing in the instance as first parameter.
you're right. This isn't possible with enum. But why not just use a good old class:
public class MyStrategy {
public MyStrategy() {
buildUp();
}
public void executeChoosenMethod(int i) {
actions.get(i).execute();
}
private void action1() {
System.out.println("action1");
}
private void action2() {
System.out.println("action2");
}
private List<InvokeAction> actions = new ArrayList<>();
private void buildUp() {
actions.add(this::action1);
actions.add(this::action2);
}
#FunctionalInterface
private interface InvokeAction {
void execute();
}
}

Categories