Giter VIP home page Giter VIP logo

Comments (6)

ericbottard avatar ericbottard commented on May 18, 2024

Hi Felipe,

there is no official way of disabling converters, but I think you can easily achieve this by making sure your own converter gets registered after the standard one and has the same name (dateConverter). This should work.

from spring-shell.

felipecao avatar felipecao commented on May 18, 2024

Hi @ericbottard , thanks a lot for the super fast response!

How can I ensure my converter gets after the standard one?

Right now, my DateConverter looks like this:

package cli.converters;

import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Component
public class DateConverter implements Converter<Date>
{
    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    private final DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);

    @Override
    public boolean supports(Class<?> type, String optionContext)
    {
        return Date.class.isAssignableFrom(type);
    }

    @Override
    public Date convertFromText(String value, Class<?> targetType, String optionContext)
    {
        try {
            return dateFormat.parse(value);
        }
        catch (ParseException e) {
            throw new IllegalArgumentException("Could not parse date: " + e.getMessage());
        }
    }

    @Override
    public boolean getAllPossibleValues(List<Completion> completions, Class<?> targetType, String existingData, String optionContext, MethodTarget target)
    {
        return false;
    }
}

And when I try to start the CLI I get this error:

Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from URL [file:/Users/felipe/workspace/rebuy-java-cli/target/classes/META-INF/spring/spring-shell-plugin.xml]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'dateConverter' for bean class [com.rebuy.cli.converters.DateConverter] conflicts with existing, non-compatible bean definition of same name and class [org.springframework.shell.converters.DateConverter]
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:414)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181)
Disconnected from the target VM, address: '127.0.0.1:51111', transport: 'socket'
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:217)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:252)
    at org.springframework.shell.Bootstrap.<init>(Bootstrap.java:101)
    at org.springframework.shell.Bootstrap.<init>(Bootstrap.java:76)
    at org.springframework.shell.Bootstrap.main(Bootstrap.java:58)
    at com.rebuy.cli.Main.main(Main.java:11)
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'dateConverter' for bean class [com.rebuy.cli.converters.DateConverter] conflicts with existing, non-compatible bean definition of same name and class [org.springframework.shell.converters.DateConverter]
    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:320)
    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:259)
    at org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(ComponentScanBeanDefinitionParser.java:87)
    at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:74)
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1411)
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1401)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:168)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:138)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:94)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:508)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:392)
    ... 10 more

Should I do anything else?

from spring-shell.

ericbottard avatar ericbottard commented on May 18, 2024

Wow, sorry this seems to be a (new?) behavior in Spring core. Back in the day, when I was still a kid, you could override a bean definition just by having it appear afterwards in the scanning order :)

Anyway, in the meantime I would say your best bet is to have a look at Spring Shell's Bootstrap class and replicate it yourself, bypassing the unconditional registration of all standard converters.

I will still have a look at this, as this seems like something users would want to do.

from spring-shell.

ericbottard avatar ericbottard commented on May 18, 2024

As a matter of fact, it seems like this overriding mechanism I was talking about indeed works, if you declare your bean via xml notation.

So, I'd recommend doing something like this:
I assume you currently have a spring-shell-plugin.xml file that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.acme.whatever" />

/>
</beans>

Change it to this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.acme.whatever" />

    <bean id="dateConverter" class="cli.converter.DateConverter" />
</beans>

(Drop the @Component on your DateConverter and/or make sure it is not being component scanned)

from spring-shell.

felipecao avatar felipecao commented on May 18, 2024

Works like a charm! Thanks a bunch for the super fast responses!

from spring-shell.

ericbottard avatar ericbottard commented on May 18, 2024

My pleasure :)

from spring-shell.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.