I have a service shown below
public interface SomeService{
#GetMapping("/someapi")
public Object getData();
}
i have impl class shown below
public class ServiceImpl{
private boolen isSomeCondition;
public Object getData(){
callSomeMethod();
if(isSomeCondition)
//do something
else
//do some other
}
public void callSomeMethod(){
if(someCondition)
//do something
else
//set isSomeCondition to true
isSomeCondition=true;
}
i want this isSomeCondition to be set to false initially for every call to the "/someapi" and later to be changed when callSomeMethod is executed. whatever i have above doesn't seem to work as global variable isSomeCondition is stateless bean.
what could be alternatives to this?
If you require state, then introduce state. Create a stateful object for each request:
public class ServiceImpl{
public Object getData(){
final DataGetter getter = new DataGetter();
return getter.getData();
}
static class DataGetter {
private boolen isSomeCondition;
public Object getData(){
callSomeMethod();
if(isSomeCondition) {
//do something
} else {
//do some other
}
}
public void callSomeMethod(){
if(someCondition) {
//do something
} else {
//set isSomeCondition to true
isSomeCondition=true;
}
}
}
}
Since you are using Spring, changing the bean scope might be an option too:
#RequestScope
public class ServiceImpl {
// ...
}
Try something like below. Instead of having isSomeCondition as global variable have it as local variable and pass it to the method.
public class ServiceImpl{
public Object getData(){
private boolen isSomeCondition;
isSomeCondition = callSomeMethod(isSomeCondition);
if(isSomeCondition)
//do something
else
//do some other
}
Here based on your condition you can set it and return.
public boolean callSomeMethod(){
if(someCondition)
//do something
else
//set isSomeCondition to true
isSomeCondition=true;
return isSomeCondition;
}
Related
I have a class with many public methods. Each method executes a single task when a single condition is met. The conditions in all methods are exactly the same as seen below:
public class MyClass{
public ClassA method1 (arguments...){
if(condition(aLong, aString)){
return doSomething(arguments...)
}else{
throw new CustomException();
}
}
public void method2 (arguments...){
if(condition(aLong, aString)){
doSomethingElse(arguments...)
}else{
throw new CustomException();
}
}
public List<ClassB> method3 (arguments...){
if(condition(aLong, aString)){
return doSomethingDifferent(arguments...)
}else{
throw new CustomException();
}
}
private boolean condition(Long aLong, String aString){
// some code
return true;
}
}
I wanted to get rid of the repeating if...else condition by using the command pattern, so i created a class like below to wrap the actual execution inside an if else statement.
public abstract class ValidCommand<T extends Serializable> {
private BiPredicate<Long,String> predicate;
private Long aLong;
private String aString
public ValidCommand(BiPredicate<Long,String> predicate,Long aLong, String aString){
this.predicate = predicate;
this.aLong = aLong;
this.aString = aString;
}
public T execute(){
if(predicate.test(playlistId, requestUserId)){
return onExecution();
}else{
throw new CustomException();
}
}
protected abstract T onExecution();
}
and I refactored the class with the methods as below:
public class MyClass{
private BiPredicate<Long,String> predicate = (a,b) -> condition(a,b);
public ClassA method1(arguments...){
ValidCommand<ClassA> validCommand= new ValidCommand(predicate,aLong,aString){
#Override
protected Serializable onExecution() {
return doSomething();
}
};
return validCommand.execute();
}
.
.
.
}
My question is if there is a better way of doing this in Java and if is worth bothering in terms of code readability and DRY principles. Note that the number of methods inside MyClass may increase and probably all of them will share the same condition.
What about creating a utility function:
private void validate(Long aLong, String aString) {
if (!condition(aLong, aString)){
throw new CustomException();
}
}
and then adjusting your code to use it like:
public ClassA method1 (arguments...){
validate(aLong, aString);
return doSomething(arguments...);
}
i recently asked a question on how to code my statemachine in a clean way. normally i code for PLC`s so im no expert in java.
i got an helpfull answer to model the states as an enum, and encapsulate the transition logic inside the enums, like this:
public enum State {
s00_StandBy {
#Override
public State nextState() {
// if...
return ...;
}
},
s10_DetermineOperation {
#Override
public State nextState() {
// if ...
return ....;
}
},
public abstract State nextState();
}
But i am having trouble implementing this myself.
First thing is why cant i use certain conditions inside the enum cases?
example:
boolean resetBtn,startBtn;
State currentState;
//Transition logic
public enum State {
//if state is s00_standBy and startBtn is true proceed to s10
s00_StandBy {
#Override
public State nextState() {
if(startBtn){ // Cant use startBtn here? how to use conditions from outside the enum case?
return s10_DetermineOperation;
}
}
};
public abstract State nextState();
}
//Main
public void main() throws Exception {
//while in this state do stuff
if(currentState.equals(State.s00_StandBy)) {
//when done or condition is met go to next state
currentState.nextState();
}
}
second problem im up against is, how do you code the enum encapsulated transitions to have multiple conditions to proceed to a single new state?
like normally i would program the transition sort of like this:
//state
if (currentState.equals(s10_DetermineOperation) && resetBtn = true)
Or (currentState.equals(s20_normalOperation) && resetBtn=true)
Or (currentState.equals(s30_someOtherState) && resetBtn=true){
return state.s00_StandBy;}
but to my understanding wih the encapsulated enums you can only jump from a certain state to another and every transition have to be coded seperately?
so you get this for the above example:
boolean resetBtn,startBtn;
State currentState;
//Transition logic
public enum State {
//if state is s00_standBy and startBtn is true proceed to s10
s10_DetermineOperation {
#Override
public State nextState() {
if(startBtn){ // Cant use startBtn here? how to use conditions from outside the enum case?
return s00_StandBy;
}
}
},
s20_normalOperation {
#Override
public State nextState() {
if(resetBtn){ // Cant use startBtn here? how to use conditions from outside the enum case?
return s00_StandBy;
}
}
},
s30_normalOperation {
#Override
public State nextState() {
if(resetBtn){ // Cant use startBtn here? how to use conditions from outside the enum case?
return s00_StandBy;
}
}
},
public abstract State nextState();
}
this gets out of hand fast when you have a lot of transitions, what am i doing wrong here?
There could be several solutions.
Instead of only one method for doing the transition, you could have one for evvery trigger, buttons in your case.
For example:
public abstract State startButtonPressed();
public abstract State resetButtonPressed();
And implement this methods in every state.
Another way, is to encapsulate the fields you need to access in a class, for example Context, an add it as an argument to the state transition method(s).
public abstract State nextState(Context context);
public State nextState(Context context) {
if(context.startBtn){
return s00_StandBy;
}
}
Of course, both solutions can be combined.
Edit
An example using context:
The context class:
public class Context {
private boolean bool1;
private boolean bool2;
public Context() {
}
public boolean isBool1() {
return bool1;
}
public void setBool1(boolean bool1) {
this.bool1 = bool1;
}
public boolean isBool2() {
return bool2;
}
public void setBool2(boolean bool2) {
this.bool2 = bool2;
}
}
The enum:
public enum State {
s00_StandBy {
#Override
public State nextState(Context context) {
if (context.isBool1()) {
return s99_otherState;
} else {
return s20_someOtherState;
}
}
},
s20_someOtherState {
#Override
public State nextState(Context context) {
if (context.isBool2()) {
return s99_otherState;
} else {
return s00_StandBy;
}
}
},
s99_otherState {
#Override
public State nextState(Context context) {
return s00_StandBy;
}
};
public abstract State nextState(Context context);
}
An example main method:
public class Main {
public static void main(String... args) {
Context context = new Context();
State currentState = State.s00_StandBy;
context.setBool1(true);
currentState = currentState.nextState(context);
System.out.println(currentState);
}
}
I have a static object in a class.
public class AppHelper {
public static MyObject CONSTANT_ = new MyObject();
}
// and my object
public class MyObject {
private Integer status;
// get and set for status
}
public class MyActivity extends Activity {
// oncreate()
// onresume()
public void OnUpdate() {
if (AppHelper.CONSTANT_.getStatus == 1) {
// doStuff
} else if (AppHelper.CONSTANT_.getStatus == 2) {
// doOtherStuff
}
}
}
public class MyService extends Service {
// oncreate()
public void callServer() {
// implementation of thread ommited
Endpoint.get(URL, new CallBack(Response response) {
AppHelper.CONSTANT_ = jsonToObj(reponse); // method for conversion is Ok
});
}
}
And activities have to call AppHelper.CONSTANT_.getStatus() for show a different view. My thread updates CONSTANT_ object constantly.
So, sometimes I use something like this:
MyObject obj = AppHelper.CONSTANT_;
When I set any field in obj, few seconds later the setted field come back to empty. Is obj linked with AppHelper.CONSTANT_ ? If so, have some other way to supply this status field without have a constant?
I've run into a problem in which my class contains several methods with a lot of duplicated code. The reason behind this is that each method traverses a list of entries and calls specific entry method.
In code...
The LowLevelClass class has the following structure:
public class LowLevelClass {
// constructor omitted
public boolean doSomethingA() {
// some non-duplicated code
return true;
}
public boolean doSomethingB() {
// some non-duplicated code
return true;
}
public boolean doSomethingC() {
// some non-duplicated code
return true;
}
}
The top level class contains a List of LowLevelClasses and has the same number of methods, but this time, with a lot of duplications:
public class HighLevelClass {
private List<LowLevelClass> classes = new ArrayList<>();
public HighLevelClass() {
this.classes.add(new LowLevelClass(/* params */));
this.classes.add(new LowLevelClass(/* params */));
this.classes.add(new LowLevelClass(/* params */));
}
public void doA() {
System.out.println("Doing ...");
for (LowLevelClass entry : classes) {
System.out.println("Doing something...");
entry.doSomethingA();
System.out.println("Done");
}
}
public void doB() {
System.out.println("Doing ...");
for (LowLevelClass entry : classes) {
System.out.println("Doing something...");
entry.doSomethingB();
System.out.println("Done");
}
}
public void doC() {
System.out.println("Doing ...");
for (LowLevelClass entry : classes) {
System.out.println("Doing something...");
entry.doSomethingC();
System.out.println("Done");
}
}
}
My goal is to have something in form of:
public class HighLevelClass {
private List<LowLevelClass> classes = new ArrayList<>();
public HighLevelClass() {
this.classes.add(new LowLevelClass());
this.classes.add(new LowLevelClass());
this.classes.add(new LowLevelClass());
}
public void doSomething(Lambda /* Functional interface*/ operation) {
System.out.println("Doing A");
for (LowLevelClass entry : classes) {
System.out.println("Doing something...");
entry.operation; // or something else...
System.out.println("Done");
}
}
public void doSomethingA() {
// my goal... and maybe in totally wrong direction is to send something in form of...
return doSomething(LowLevelClass::doSomethingA);
}
// etc
}
Can this be done in Java 8 with Lambdas? In other words, can I define the method to perform on each entry of the given list?
EDIT 1
The answers provided by Jorn Vernee and Joffrey are correct!
Ultimately, the solution was to use Predicate. (see EDIT 2 why I didn't use Consumer in the end...)
public class HighLevelClass {
private List<LowLevelClass> classes = new ArrayList<>();
public HighLevelClass() {
this.classes.add(new LowLevelClass());
this.classes.add(new LowLevelClass());
this.classes.add(new LowLevelClass());
}
public boolean doSomething(Predicate<LowLevelClass> function) {
System.out.println("Doing A");
for (LowLevelClass entry : classes) {
System.out.println("Doing something...");
boolean val = function.test(entry);
System.out.println("Done " + val);
}
return someEndVerdict;
}
public boolean doSomethingA() {
return doSomething(LowLevelClass::doSomethingA);
}
// etc
}
EDIT 2
My initial methods in HighLevelClass didn't contain boolean return type. That's the reason why I used Predicate (Predicate, as a contast to Consumer, returns boolean value which suited me better - and which I forgot to initially mention :((( )
Thanks for help and time!
You should not confuse the way you call a method, which may or may not involve a lambda, and the way you write a method, which involves finding the right argument types.
When you write a method, you need to focus on your arguments' types. If one of them is an object representing a function, what you need is to understand the appropriate signature that this function should match, and this will give you the functional interface you should put as type of your param.
In your case, you expect a function that takes 1 argument of type LowLevelClass and returns no value. You might be surprised by that, but you need to think of instance methods as functions that take an instance of the class (this) as an extra first argument (as opposed to static methods).
Therefore, the Consumer<LowLevelClass> interface is what you want:
public void doSomething(Consumer<LowLevelClass> operation) {
System.out.println("Doing A");
for (LowLevelClass entry : classes) {
System.out.println("Doing something...");
operation.accept(entry); // or something else...
System.out.println("Done");
}
}
public void doSomethingA() {
return doSomething(LowLevelClass::doSomethingA);
}
I'm not a Java specialist and wondering if I could wrap Methods that are only different in their middle to stop having boilerplatecode like this:
public boolean storeAnimals(Cage cage, Collection<Anmial> animals, IConfiguration configuration) {
checkPrerequisite(cage);
String cagePath = cage.getPath();
AnimalStorage animalStore = AnimalStorage.openFile(cage, configuration);
//***/
do_sth_very_special
//***/
animalStore.closeFile();
return true;
}
public Collection<Anmial> getRedAnimals(Cage cage, IConfiguration configuration) {
checkPrerequisite(cage);
String cagePath = cage.getPath();
File animalStore = AnimalStorage.openFile(cage, configuration);
//***/
do_sth_very_special
//***/
animalStore.closeFile();
return result;
}
Since java doesn't present a kind of closure, you could use an interface for it. In this case you could do something like:
public Collection<Anmial> commonMethod(Cage cage, IConfiguration configuration, Runnable runnable) {
checkPrerequisite(cage);
String cagePath = cage.getPath();
File animalStore = AnimalStorage.openFile(cage, configuration);
//***/
runnable.run();
//***/
animalStore.closeFile();
return result;
}
and you method would be something like:
public boolean storeAnimals(Cage cage, Collection<Anmial> animals, IConfiguration configuration) {
commonMethod(cage, animals, configuration, new Runnable() {
public void run() {
System.out.println("something special");
}
});
return true;
}
of course the Runnable interface was taken just to exemplify the idea, you could implement an interface for your needs. If you need that the inner code accesses some variables defined outside you can pass it as parameters, and if the outside code needs to access some variables defined inside you could return them from the invocation.
You could define a generic interface like:
public interface Executable<ReturnType, ParameterType> {
ReturnType execute(ParameterType parameter);
}
In case you need more parameters to execute the code, you could build a class containing all needed fields for the code execution. The same could be applied to the result.
This would be the idea to return a list of string:
new Executable<List<String>, Void>() {
public List<String> execute(Void void) {
// something special
return new ArrayList<String>();
}
}
ParameterObject could be used to solve the problem when you need to give more objects to the execution. Suppose you have one Integer and a boolean that needs to be given to the execution, this means you will have a class holding an Integer and a boolean like:
public class MyParameter {
private boolean b;
private Integer i;
public MyParameter(Integer i, boolean b) {
this.b = b;
this.i = i;
}
// getters
}
new Executable<Void, MyParameter>() {
public Void execute(MyParameter params) {
// something special
System.out.println(params.getI());
return null;
}
}