spring-shell icon indicating copy to clipboard operation
spring-shell copied to clipboard

BaseComponentContext containsKey is not accurate with get

Open Cui-xf opened this issue 2 years ago • 6 comments
trafficstars

ComponentFlow.ComponentFlowResult result = componentFlowBuilder.clone().reset()
                    .withConfirmationInput("id")
                    .name("确认删除?")
                    .and()
                    .build()
                    .run();

//输入y/n 之外的其他任意字符
//此时 Context {"id":null}

Boolean containsKey = result.getContext().containsKey("id"); // containsKey true
Boolean id = result.getContext().get("id"); //  throw NoSuchElementException

问题原因: org.springframework.shell.component.context.BaseComponentContext.java

...
	@Override
	public Object get(Object key) {
		Object o = super.get(key);
		if (o != null) {
			return o;
		}
		throw new NoSuchElementException("Context does not contain key: " + key);
	}
...

期望将两个方法语义统一! 3q

Cui-xf avatar Mar 06 '23 02:03 Cui-xf

I'm sorry but it is a bit difficult to understand a question what appears to be Chinese language?

jvalkeal avatar Mar 12 '23 15:03 jvalkeal

ComponentFlow.ComponentFlowResult result = componentFlowBuilder.clone().reset()
                    .withConfirmationInput("id")
                    .name("confirm?")
                    .and()
                    .build()
                    .run();

//When entering any character other than y/n
//Now result.getContext() looks like this: Context {"id":null}


// containsKey return  true
Boolean containsKey = result.getContext().containsKey("id"); 
// But it throw an exception when get the value(throw NoSuchElementException)
Boolean id = result.getContext().get("id"); 

because: org.springframework.shell.component.context.BaseComponentContext.java extends LinkedHashMap and override get() function

...
	@Override
	public Object get(Object key) {
		Object o = super.get(key);
		if (o != null) {
			return o;
		}
		throw new NoSuchElementException("Context does not contain key: " + key);
	}
...

can only be used like this:

             try {
                Boolean r = result.getContext().get("id");
                if (r != null && r) {
                   ...
                    return "done";
                } else {
                    return "canceled";
                }
            } catch (NoSuchElementException e) {
                return "invalid input";
            }

expected usage:

            if (result.getContext().containsKey("id")) {
                boolean r = result.getContext().get("id");
                return r ? "done" : "canceled";
            } else {
                return "invalid input";
            }

Cui-xf avatar Mar 16 '23 02:03 Cui-xf

Thanks clarifying your case and you're right. If containsKey is telling there is a key then it's expected that get returns something.

jvalkeal avatar Mar 17 '23 09:03 jvalkeal

Hello @jvalkeal, can you provide any update to this issue? I am facing this issue at the moment too. For me it occurs if i run or debug the spring-shell application from Intellij IDEA. If i run the application with java -jar target/app.jar it works as expected.

chhorz avatar Apr 17 '24 11:04 chhorz

Hello, I got the same issue with the latest version of spring shell (3.3.3) and GraalVM 21 with native image, in Windows Powershell terminal. When i launch a command that use a ComponentFlow, I got the following exception : java.util.NoSuchElementException: Context does not contain key: serverPort

ComponentFlow flow = componentFlowBuilder.clone().reset()
                .withConfirmationInput("changePassword")
                .name("Souhaitez-vous changer le mot de passe de l'utilisateur admin par 'admin' ?")
                .defaultValue(true)
                .and()
                .withStringInput("serverPort")
                .name("Veuillez saisir un numéro de port pour le serveur :")
                .defaultValue("auto")
                .and()
                .build();
ComponentFlow.ComponentFlowResult result = flow.run();

int serverPort = result.getContext().get("serverPort") == "auto" ? PortUtil.getNextAvailablePort(8080) : Integer.parseInt(result.getContext().get("serverPort"));

However, when using Windows Git Bash, this issue doesn't occurs. But the flow output is a bit broken... When using the jar version, everything works fine, even in Powershell.

QulOkayo avatar Oct 02 '24 13:10 QulOkayo