问:
Vaadin Combobox and LazyInitializationException
My question maybe simple simple but I don't understand why Vaadin combobox tries to get a colletion of nested entities set in a combobox if I do not call these items of collection.

See this:

```<code>@Entity
public class Estado extends AbstractEntity {

    private String nome;
    private String sigla;
    @OneToMany(mappedBy = "estado")
    private List<Municipio> municipios;

    public String getNome() {
        return nome;
    }
    public void setNome(String nome) {
        this.nome = nome;
    }
    public String getSigla() {
        return sigla;
    }
    public void setSigla(String sigla) {
        this.sigla = sigla;
    }
    public List<Municipio> getMunicipios() {
        return municipios;
    }
    public void setMunicipios(List<Municipio> municipios) {
        this.municipios = municipios;
    }

private void initCbEstados() {

    if (cbEstados.isEmpty()) {
        List<Estado> estados = estadoService.findAllEager();
        cbEstados.setItems(estados);
    }

    cbEstados.addValueChangeListener(e -> updateCbMunicipios());

    cbEstados.setClearButtonVisible(true);

    cbEstados.setItemLabelGenerator(Estado::getNome);

    cbEstados.setWidth("50%");

}

private void updateViewToEdit(){

    if (isEditMode) {

        Estado estado = entity.getEndereco().getEstado();

    ***//this throws LazyInitializationException***
        cbEstados.setValue(estado);

        updateCbMunicipios();
    }
</code>```

I do not call at any time estado.getMunicipios. But apparently the behavior of the combobox tries to infer in the municipios released the exception.

Is this expected behavior?

I don't think it should be?

答:
Sory, fisrt post on stack overflow and i was not familiar with the platform and ended not posting the entire code. The error occurred in

cbEstados.addValueChangeListener(e -> updateCbMunicipios());

that during the debug was not visible because it was occurring within the vaadin classes. The problem was solved by searching for the municpios in updateCbMunicpios();  So when FormBase calls   beforeEnter(BeforeEnterEvent event) the readBean() set values on cbEstados that fires ValuechangeListener and load the LazeInicializaTionExceptions because Entity comes from the Request Scoope and not Fully filed to set the Value of Municipio in cbMunicipios. And cbMunicipios would be empty firing anhoter error from Vaadin.

```<code>public class FornecedorForm extends CadastroFormBaseGenerics<Fornecedor, FornecedorService> {

    private static final long serialVersionUID = -5599427454458715210L;

    EstadoService estadoService;

    @PropertyId("ativo")
    private Checkbox ckAtivo;

    @PropertyId("razaoSocial")
    private TextField txtRazaoSocial;

    @PropertyId("nomeFantasia")
    private TextField txtNomeFantasia;

    @PropertyId("cnpj")
    private TextField txtCnpj;

    @PropertyId("contato")
    private TextField txtContato;

    @PropertyId("telefoneContato")
    private TextField txtTelContato;

    @PropertyId("telefone")
    private TextField txtTelefone;

    @PropertyId("observacao")
    TextArea txtObservacao;

    private ComboBox<Estado> cbEstados;

    private ComboBox<Municipio> cbMunicipios;

    private TextField txtCep;

    private TextField txtLogradouro;

    private TextField txtNumero;

    private TextField txtComplemento;

    @PropertyId("emailContato")
    EmailField txtEmailContato;

    private FormLayout layout;

    HorizontalLayout layoutEstado;

    public FornecedorForm(@Autowired EstadoService estadoService) {
        super(Fornecedor.class, "Fornecedor");
        this.estadoService = estadoService;

        updateViewToEdit();

    }

    protected void configureAdditionalBinds() {

        getBinder().bind(cbEstados, "endereco.estado");
        getBinder().bind(cbMunicipios, "endereco.municipio");
        getBinder().bind(txtCep, "endereco.cep");
        getBinder().bind(txtLogradouro, "endereco.logradouro");
        getBinder().bind(txtNumero, "endereco.numero");
        getBinder().bind(txtComplemento, "endereco.complemento");

    }

    private void initCbEstados() {

        cbEstados = new ComboBox<Estado>("Estado");

        List<Estado> estados = estadoService.findAllEager();
        cbEstados.setItems(estados);

        cbEstados.addValueChangeListener(e -> updateCbMunicipios());

        cbEstados.setClearButtonVisible(true);

        cbEstados.setItemLabelGenerator(Estado::getNome);

        cbEstados.setWidth("50%");

    }

    private void initCbMunicpios() {

        cbMunicipios = new ComboBox<Municipio>("Município");
        cbMunicipios.setItemLabelGenerator(Municipio::getNome);
        cbMunicipios.setWidth("50%");
        cbMunicipios.setReadOnly(true);

    }

    private void updateCbMunicipios() {

        if (cbEstados.getValue() != null) {

            cbMunicipios.clear();

            cbMunicipios.setReadOnly(false);

            Estado estado = estadoService.findMunicipios(cbEstados.getValue());

            cbMunicipios.setItems(estado.getMunicipios());

        } else {
            cbMunicipios.clear();
            cbMunicipios.setReadOnly(true);
        }

    }

    @Override
    protected void initViewComponents() {

        layoutEstado = new HorizontalLayout();

        layout = new FormLayout();

        layoutEstado.setSizeFull();

        initCbEstados();
        initCbMunicpios();

        ckAtivo = new Checkbox("Ativo ?", true);
        txtRazaoSocial = new TextField("Razão Social");
        txtNomeFantasia = new TextField("Nome Fantasia");
        txtCnpj = new TextField("CNPJ");
        txtCnpj.setWidth("25%");
        // txtCnpj.setErrorMessage("CNPJ Incorreto.");
        // txtCnpj.setPattern("^[0-9]{2}?[-s.]?[0-9]{3}[-s.]?[0-9]{3}[-s/]?[0-9]{4}[-s-]?[0-9]{2}$");

        txtTelefone = new TextField("Telefone");

        txtContato = new TextField("Nome Contato");

        txtTelContato = new TextField("Telefone Contato");

        txtEmailContato = new EmailField("Email Contato");
        txtEmailContato.setClearButtonVisible(true);
        txtEmailContato.setErrorMessage("Formato do E-mail incorreto");
        txtEmailContato.setRequiredIndicatorVisible(false);

        txtLogradouro = new TextField("Logradouro");

        txtNumero = new TextField("Número");
        txtNumero.setWidth("50px");

        txtCep = new TextField("CEP");
        txtCep.setPattern("^[0-9]{5}?[-s-]?[0-9]{3}$");
        txtCep.setPlaceholder("00000-000");
        txtCep.setRequired(true);
        txtCep.setErrorMessage("Informe o CEP");

        txtCep.setWidth("75px");

        txtComplemento = new TextField("Complemento");

        txtObservacao = new TextArea("Observações");

        layout.add(ckAtivo, 2);
        layout.add(txtCnpj, 2);
        layout.add(txtRazaoSocial, txtNomeFantasia);

        layout.add(layoutEstado, 2);

        layout.add(txtLogradouro, txtNumero);
        layout.add(txtComplemento, txtCep, txtTelefone);

        HorizontalLayout layoutContato = new HorizontalLayout(txtContato, txtTelContato, txtEmailContato);
        layoutContato.setSizeFull();
        txtContato.setWidth("40%");
        txtEmailContato.setWidth("40%");
        txtTelContato.setWidth("20%");

        layout.add(layoutContato, 2);

        layout.add(txtObservacao, 2);

        super.formLayout.add(layout);

        layoutEstado.add(cbEstados, cbMunicipios);

        configureAdditionalBinds();

    }

    protected void updateViewToEdit() {

        if (isEditMode) {

            Estado estado = entity.getEndereco().getEstado();
            estado = estadoService.findMunicipios(estado);

            cbEstados.setValue(estado);

        }

    }

    @Override
    protected void getNewEntityToPersist() {

        entity = new Fornecedor();
        entity.setEndereco(new Endereco());
        ckAtivo.setValue(true);

    }

}

public abstract class CadastroFormBaseGenerics<T, SERVICE extends ServiceInterface<T>> extends FormLayout
        implements BeforeEnterObserver {

    private static final long serialVersionUID = 7069232922824142288L;

    protected T entity;
    @Autowired
    private SERVICE service;

    private final Class<T> beanClass;

    private Binder<T> binder;

    private String nomeDoBean;
    protected boolean isEditMode;

    private Button btnSave = new Button("Salvar");
    private Button btnDelete = new Button("Excluir");
    private Button btnCancel = new Button("Cancelar");

    protected VerticalLayout formLayout = new VerticalLayout();;

    private HorizontalLayout buttonsLayout = new HorizontalLayout();

    public CadastroFormBaseGenerics(Class<T> beanClass, String nomeDoBean) {

        this.beanClass = beanClass;

        this.nomeDoBean = nomeDoBean;

    }

    protected abstract void initViewComponents();

    @PostConstruct
    private void inicialize() {

        checkEditMode();

        initBinder();

        initViewComponents();

        addComponentAsFirst(formLayout);

        configureFormLayout();

        getEntityToEdit();

        updateViewToEdit();

    }

    protected abstract void updateViewToEdit();

    protected void initBinder() {

        binder = new BeanValidationBinder<T>(beanClass);

    }

    protected void setPlaceHolders(String beanName) {

        String primeiraLetra = "" + beanName.charAt(0);

        primeiraLetra = primeiraLetra.toUpperCase();
        char letraMaiuscula = primeiraLetra.charAt(0);

        char[] cArray = beanName.toCharArray();

        cArray[0] = letraMaiuscula;

        beanName = new String(cArray);

        for (int i = 0; i < formLayout.getComponentCount(); i++) {

            Component c = formLayout.getComponentAt(i);

            if (c.getClass().getName().equals("com.vaadin.flow.component.textfield.TextField")) {

                TextField aux = (TextField) c;
                aux.setPlaceholder(aux.getLabel() + " " + beanName + "...");
                aux.setClearButtonVisible(true);

            }

        }
    }

    protected void configureFormLayout() {

        formLayout.setSizeFull();

        // formLayout.setMargin(true);
        formLayout.setSpacing(true);
        formLayout.setPadding(true);
        formLayout.setAlignItems(Alignment.AUTO);
        formLayout.setMargin(true);
        // add(formLayout, 2);

        configureButtonsLayout();

    }

    void configureButtonsLayout() {

        btnDelete.setVisible(false);

        btnSave.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
        btnDelete.addThemeVariants(ButtonVariant.LUMO_ERROR);

        buttonsLayout = new HorizontalLayout();

        buttonsLayout.add(btnSave, btnDelete, btnCancel);
        buttonsLayout.setMargin(true);

        buttonsLayout.setPadding(true);
        buttonsLayout.setSizeFull();

        configureButtonEvents();

        add(buttonsLayout, 2);

    }

    private void configureButtonEvents() {

        btnSave.addClickListener(saveEvent -> save());
        btnDelete.addClickListener(deleteEvent -> delete());
        btnCancel.addClickListener(cancelEvent -> clearForm());

    }

    private void save() {

        String msg = nomeDoBean + " Alterada(o) com sucesso.";

        if (!isEditMode) {

            msg = nomeDoBean + " Cadastrada(o) com sucesso.";
            getNewEntityToPersist();

            // getNewEntity();

        }

        try {
            getBinder().writeBean(entity);
            service.save(entity);
            clearForm();
            showSucess(msg);

        } catch (DoisCsCrudException e) {

            showWarnig(nomeDoBean + " já cadastrado. Verique.");
            logException(e, "Metodo save()");

        } catch (ValidationException e) {

            showWarnig("Verique os campos obrigatórios.");

        }

    }

    /**
     * {@summary} Você deve implementar o {@code} entity = New POJO este método é
     * chamado toda vez que {@code} save() para criar um novo BEAN a ser persistido.
     */
    protected abstract void getNewEntityToPersist();

    private void delete() {
        try {

            service.delete(entity);
            clearForm();
            showSucess(nomeDoBean + " removida(o) com sucesso.");

        } catch (DoisCsCrudException e) {
            showWarnig(nomeDoBean + " não pode ser removida(o), pois existem registros que dependem dele. %/n "
                    + "Inative-o para que não seja mais exibido.");
        }

    }

    @SuppressWarnings("unchecked")
    private void getEntityToEdit() throws ClassCastException {

        if (isEditMode) {

            btnDelete.setVisible(true);
            this.entity = (T) VaadinServletRequest.getCurrent().getAttribute("entityToEdit");

        }

    }

    private boolean checkEditMode() {

        if (VaadinServletRequest.getCurrent().getAttribute("entityToEdit") != null) {

            isEditMode = true;
        } else {
            isEditMode = false;
        }

        return isEditMode;

    }

    /**
     * Sempre deve ser chamado após um click no botão salvar, cancelar ou excluir
     */
    protected void clearForm() {

        // Desabilita o botão para excluir um Bean Cadastrado
        btnDelete.setVisible(false);

        // Seta editmode para falso, garantido que a proxima interação
        // seja com um bean novo
        isEditMode = false;

        clearBinder();

    }

    protected void clearBinder() {

        binder.readBean(null);

    }

    protected void showSucess(String message) {

        createNotification(message, NotificationVariant.LUMO_SUCCESS, 3000);

    }

    protected void showError(String message) {

        createNotification(message, NotificationVariant.LUMO_ERROR, 5000);

    }

    protected void showWarnig(String message) {
        createNotification(message, NotificationVariant.LUMO_CONTRAST, 10000);

    }

    private void createNotification(String message, NotificationVariant variant, int duration) {

        Notification n = new Notification(message);
        n.setDuration(7000);
        n.addThemeVariants(variant);
        n.setPosition(Position.TOP_CENTER);

        n.open();

    }

    protected void logException(Exception e, String logDesc) {

        System.out.println("################  " + logDesc.toUpperCase() + " $$ " + getClass().getSimpleName()
                + "  ################");

        e.printStackTrace();

    }

    public Binder<T> getBinder() {
        return binder;
    }

    @Override
    public void beforeEnter(BeforeEnterEvent event) {

        binder.bindInstanceFields(this);
        if (entity != null) {

            getBinder().readBean(entity);

        }

    }

}
</code>```

Body:
My question maybe simple simple but I don't understand why Vaadin combobox tries to get a colletion of nested entities set in a combobox if I do not call these items of collection.

See this:

@Entity
public class Estado extends AbstractEntity {

    private String nome;
    private String sigla;
    @OneToMany(mappedBy = "estado")
    private List<Municipio> municipios;

    public String getNome() {
        return nome;
    }
    public void setNome(String nome) {
        this.nome = nome;
    }
    public String getSigla() {
        return sigla;
    }
    public void setSigla(String sigla) {
        this.sigla = sigla;
    }
    public List<Municipio> getMunicipios() {
        return municipios;
    }
    public void setMunicipios(List<Municipio> municipios) {
        this.municipios = municipios;
    }

private void initCbEstados() {

    if (cbEstados.isEmpty()) {
        List<Estado> estados = estadoService.findAllEager();
        cbEstados.setItems(estados);
    }

    cbEstados.addValueChangeListener(e -> updateCbMunicipios());

    cbEstados.setClearButtonVisible(true);

    cbEstados.setItemLabelGenerator(Estado::getNome);

    cbEstados.setWidth("50%");

}

private void updateViewToEdit(){

    if (isEditMode) {

        Estado estado = entity.getEndereco().getEstado();

    ***//this throws LazyInitializationException***
        cbEstados.setValue(estado);

        updateCbMunicipios();
    }

I do not call at any time estado.getMunicipios. But apparently the behavior of the combobox tries to infer in the municipios released the exception.

Is this expected behavior?

I don't think it should be?

Body:
Sory, fisrt post on stack overflow and i was not familiar with the platform and ended not posting the entire code. The error occurred in

cbEstados.addValueChangeListener(e -> updateCbMunicipios());

that during the debug was not visible because it was occurring within the vaadin classes. The problem was solved by searching for the municpios in updateCbMunicpios();  So when FormBase calls   beforeEnter(BeforeEnterEvent event) the readBean() set values on cbEstados that fires ValuechangeListener and load the LazeInicializaTionExceptions because Entity comes from the Request Scoope and not Fully filed to set the Value of Municipio in cbMunicipios. And cbMunicipios would be empty firing anhoter error from Vaadin.

public class FornecedorForm extends CadastroFormBaseGenerics<Fornecedor, FornecedorService> {

    private static final long serialVersionUID = -5599427454458715210L;

    EstadoService estadoService;

    @PropertyId("ativo")
    private Checkbox ckAtivo;

    @PropertyId("razaoSocial")
    private TextField txtRazaoSocial;

    @PropertyId("nomeFantasia")
    private TextField txtNomeFantasia;

    @PropertyId("cnpj")
    private TextField txtCnpj;

    @PropertyId("contato")
    private TextField txtContato;

    @PropertyId("telefoneContato")
    private TextField txtTelContato;

    @PropertyId("telefone")
    private TextField txtTelefone;

    @PropertyId("observacao")
    TextArea txtObservacao;

    private ComboBox<Estado> cbEstados;

    private ComboBox<Municipio> cbMunicipios;

    private TextField txtCep;

    private TextField txtLogradouro;

    private TextField txtNumero;

    private TextField txtComplemento;

    @PropertyId("emailContato")
    EmailField txtEmailContato;

    private FormLayout layout;

    HorizontalLayout layoutEstado;

    public FornecedorForm(@Autowired EstadoService estadoService) {
        super(Fornecedor.class, "Fornecedor");
        this.estadoService = estadoService;

        updateViewToEdit();

    }

    protected void configureAdditionalBinds() {

        getBinder().bind(cbEstados, "endereco.estado");
        getBinder().bind(cbMunicipios, "endereco.municipio");
        getBinder().bind(txtCep, "endereco.cep");
        getBinder().bind(txtLogradouro, "endereco.logradouro");
        getBinder().bind(txtNumero, "endereco.numero");
        getBinder().bind(txtComplemento, "endereco.complemento");

    }

    private void initCbEstados() {

        cbEstados = new ComboBox<Estado>("Estado");

        List<Estado> estados = estadoService.findAllEager();
        cbEstados.setItems(estados);

        cbEstados.addValueChangeListener(e -> updateCbMunicipios());

        cbEstados.setClearButtonVisible(true);

        cbEstados.setItemLabelGenerator(Estado::getNome);

        cbEstados.setWidth("50%");

    }

    private void initCbMunicpios() {

        cbMunicipios = new ComboBox<Municipio>("Município");
        cbMunicipios.setItemLabelGenerator(Municipio::getNome);
        cbMunicipios.setWidth("50%");
        cbMunicipios.setReadOnly(true);

    }

    private void updateCbMunicipios() {

        if (cbEstados.getValue() != null) {

            cbMunicipios.clear();

            cbMunicipios.setReadOnly(false);

            Estado estado = estadoService.findMunicipios(cbEstados.getValue());

            cbMunicipios.setItems(estado.getMunicipios());

        } else {
            cbMunicipios.clear();
            cbMunicipios.setReadOnly(true);
        }

    }

    @Override
    protected void initViewComponents() {

        layoutEstado = new HorizontalLayout();

        layout = new FormLayout();

        layoutEstado.setSizeFull();

        initCbEstados();
        initCbMunicpios();

        ckAtivo = new Checkbox("Ativo ?", true);
        txtRazaoSocial = new TextField("Razão Social");
        txtNomeFantasia = new TextField("Nome Fantasia");
        txtCnpj = new TextField("CNPJ");
        txtCnpj.setWidth("25%");
        // txtCnpj.setErrorMessage("CNPJ Incorreto.");
        // txtCnpj.setPattern("^[0-9]{2}?[-s.]?[0-9]{3}[-s.]?[0-9]{3}[-s/]?[0-9]{4}[-s-]?[0-9]{2}$");

        txtTelefone = new TextField("Telefone");

        txtContato = new TextField("Nome Contato");

        txtTelContato = new TextField("Telefone Contato");

        txtEmailContato = new EmailField("Email Contato");
        txtEmailContato.setClearButtonVisible(true);
        txtEmailContato.setErrorMessage("Formato do E-mail incorreto");
        txtEmailContato.setRequiredIndicatorVisible(false);

        txtLogradouro = new TextField("Logradouro");

        txtNumero = new TextField("Número");
        txtNumero.setWidth("50px");

        txtCep = new TextField("CEP");
        txtCep.setPattern("^[0-9]{5}?[-s-]?[0-9]{3}$");
        txtCep.setPlaceholder("00000-000");
        txtCep.setRequired(true);
        txtCep.setErrorMessage("Informe o CEP");

        txtCep.setWidth("75px");

        txtComplemento = new TextField("Complemento");

        txtObservacao = new TextArea("Observações");

        layout.add(ckAtivo, 2);
        layout.add(txtCnpj, 2);
        layout.add(txtRazaoSocial, txtNomeFantasia);

        layout.add(layoutEstado, 2);

        layout.add(txtLogradouro, txtNumero);
        layout.add(txtComplemento, txtCep, txtTelefone);

        HorizontalLayout layoutContato = new HorizontalLayout(txtContato, txtTelContato, txtEmailContato);
        layoutContato.setSizeFull();
        txtContato.setWidth("40%");
        txtEmailContato.setWidth("40%");
        txtTelContato.setWidth("20%");

        layout.add(layoutContato, 2);

        layout.add(txtObservacao, 2);

        super.formLayout.add(layout);

        layoutEstado.add(cbEstados, cbMunicipios);

        configureAdditionalBinds();

    }

    protected void updateViewToEdit() {

        if (isEditMode) {

            Estado estado = entity.getEndereco().getEstado();
            estado = estadoService.findMunicipios(estado);

            cbEstados.setValue(estado);

        }

    }

    @Override
    protected void getNewEntityToPersist() {

        entity = new Fornecedor();
        entity.setEndereco(new Endereco());
        ckAtivo.setValue(true);

    }

}

public abstract class CadastroFormBaseGenerics<T, SERVICE extends ServiceInterface<T>> extends FormLayout
        implements BeforeEnterObserver {

    private static final long serialVersionUID = 7069232922824142288L;

    protected T entity;
    @Autowired
    private SERVICE service;

    private final Class<T> beanClass;

    private Binder<T> binder;

    private String nomeDoBean;
    protected boolean isEditMode;

    private Button btnSave = new Button("Salvar");
    private Button btnDelete = new Button("Excluir");
    private Button btnCancel = new Button("Cancelar");

    protected VerticalLayout formLayout = new VerticalLayout();;

    private HorizontalLayout buttonsLayout = new HorizontalLayout();

    public CadastroFormBaseGenerics(Class<T> beanClass, String nomeDoBean) {

        this.beanClass = beanClass;

        this.nomeDoBean = nomeDoBean;

    }

    protected abstract void initViewComponents();

    @PostConstruct
    private void inicialize() {

        checkEditMode();

        initBinder();

        initViewComponents();

        addComponentAsFirst(formLayout);

        configureFormLayout();

        getEntityToEdit();

        updateViewToEdit();

    }

    protected abstract void updateViewToEdit();

    protected void initBinder() {

        binder = new BeanValidationBinder<T>(beanClass);

    }

    protected void setPlaceHolders(String beanName) {

        String primeiraLetra = "" + beanName.charAt(0);

        primeiraLetra = primeiraLetra.toUpperCase();
        char letraMaiuscula = primeiraLetra.charAt(0);

        char[] cArray = beanName.toCharArray();

        cArray[0] = letraMaiuscula;

        beanName = new String(cArray);

        for (int i = 0; i < formLayout.getComponentCount(); i++) {

            Component c = formLayout.getComponentAt(i);

            if (c.getClass().getName().equals("com.vaadin.flow.component.textfield.TextField")) {

                TextField aux = (TextField) c;
                aux.setPlaceholder(aux.getLabel() + " " + beanName + "...");
                aux.setClearButtonVisible(true);

            }

        }
    }

    protected void configureFormLayout() {

        formLayout.setSizeFull();

        // formLayout.setMargin(true);
        formLayout.setSpacing(true);
        formLayout.setPadding(true);
        formLayout.setAlignItems(Alignment.AUTO);
        formLayout.setMargin(true);
        // add(formLayout, 2);

        configureButtonsLayout();

    }

    void configureButtonsLayout() {

        btnDelete.setVisible(false);

        btnSave.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
        btnDelete.addThemeVariants(ButtonVariant.LUMO_ERROR);

        buttonsLayout = new HorizontalLayout();

        buttonsLayout.add(btnSave, btnDelete, btnCancel);
        buttonsLayout.setMargin(true);

        buttonsLayout.setPadding(true);
        buttonsLayout.setSizeFull();

        configureButtonEvents();

        add(buttonsLayout, 2);

    }

    private void configureButtonEvents() {

        btnSave.addClickListener(saveEvent -> save());
        btnDelete.addClickListener(deleteEvent -> delete());
        btnCancel.addClickListener(cancelEvent -> clearForm());

    }

    private void save() {

        String msg = nomeDoBean + " Alterada(o) com sucesso.";

        if (!isEditMode) {

            msg = nomeDoBean + " Cadastrada(o) com sucesso.";
            getNewEntityToPersist();

            // getNewEntity();

        }

        try {
            getBinder().writeBean(entity);
            service.save(entity);
            clearForm();
            showSucess(msg);

        } catch (DoisCsCrudException e) {

            showWarnig(nomeDoBean + " já cadastrado. Verique.");
            logException(e, "Metodo save()");

        } catch (ValidationException e) {

            showWarnig("Verique os campos obrigatórios.");

        }

    }

    /**
     * {@summary} Você deve implementar o {@code} entity = New POJO este método é
     * chamado toda vez que {@code} save() para criar um novo BEAN a ser persistido.
     */
    protected abstract void getNewEntityToPersist();

    private void delete() {
        try {

            service.delete(entity);
            clearForm();
            showSucess(nomeDoBean + " removida(o) com sucesso.");

        } catch (DoisCsCrudException e) {
            showWarnig(nomeDoBean + " não pode ser removida(o), pois existem registros que dependem dele. %/n "
                    + "Inative-o para que não seja mais exibido.");
        }

    }

    @SuppressWarnings("unchecked")
    private void getEntityToEdit() throws ClassCastException {

        if (isEditMode) {

            btnDelete.setVisible(true);
            this.entity = (T) VaadinServletRequest.getCurrent().getAttribute("entityToEdit");

        }

    }

    private boolean checkEditMode() {

        if (VaadinServletRequest.getCurrent().getAttribute("entityToEdit") != null) {

            isEditMode = true;
        } else {
            isEditMode = false;
        }

        return isEditMode;

    }

    /**
     * Sempre deve ser chamado após um click no botão salvar, cancelar ou excluir
     */
    protected void clearForm() {

        // Desabilita o botão para excluir um Bean Cadastrado
        btnDelete.setVisible(false);

        // Seta editmode para falso, garantido que a proxima interação
        // seja com um bean novo
        isEditMode = false;

        clearBinder();

    }

    protected void clearBinder() {

        binder.readBean(null);

    }

    protected void showSucess(String message) {

        createNotification(message, NotificationVariant.LUMO_SUCCESS, 3000);

    }

    protected void showError(String message) {

        createNotification(message, NotificationVariant.LUMO_ERROR, 5000);

    }

    protected void showWarnig(String message) {
        createNotification(message, NotificationVariant.LUMO_CONTRAST, 10000);

    }

    private void createNotification(String message, NotificationVariant variant, int duration) {

        Notification n = new Notification(message);
        n.setDuration(7000);
        n.addThemeVariants(variant);
        n.setPosition(Position.TOP_CENTER);

        n.open();

    }

    protected void logException(Exception e, String logDesc) {

        System.out.println("################  " + logDesc.toUpperCase() + " $$ " + getClass().getSimpleName()
                + "  ################");

        e.printStackTrace();

    }

    public Binder<T> getBinder() {
        return binder;
    }

    @Override
    public void beforeEnter(BeforeEnterEvent event) {

        binder.bindInstanceFields(this);
        if (entity != null) {

            getBinder().readBean(entity);

        }

    }

}


来源: stackexchange

问:
Adding Table rows Dynamically in Android
I am trying to create a layout where I need to add table rows dynamically. Below is the table layout xml

```<code><TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/displayLinear"
    android:background="@color/background_df"
    android:orientation="vertical" >

         <TableRow
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/display_row"
            android:layout_marginTop="280dip" >

</TableLayout>
</code>```

The activity file where rows are being added dynamically is

```<code>public void init(){
    menuDB = new MenuDBAdapter(this);
    ll = (TableLayout) findViewById(R.id.displayLinear);

    TableRow row=(TableRow)findViewById(R.id.display_row);
    for (int i = 0; i <2; i++) {

        checkBox = new CheckBox(this);
        tv = new TextView(this);
        addBtn = new ImageButton(this);
        addBtn.setImageResource(R.drawable.add);
        minusBtn = new ImageButton(this);
        minusBtn.setImageResource(R.drawable.minus);
        qty = new TextView(this);
        checkBox.setText("hello");
        qty.setText("10");
        row.addView(checkBox);
        row.addView(minusBtn);
        row.addView(qty);
        row.addView(addBtn);
        ll.addView(row,i);

    }
}
</code>```

But when I run this, I am getting below error

```<code>08-13 16:27:46.437: E/AndroidRuntime(23568): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.roms/com.example.roms.DisplayActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
</code>```

I understand that this is due to command ll.addView(row,i); but when I remove this its adding all stuff in a single row rather tan creating a new row for next item. I tried with giving index too as row.addView(addBtn,i) but still its not populating correctly. Please advise. Thanks.

答:
I am trying the above code with modification as per my requirement. The table is created properly. Bu the problem is when I am opening the activity 1st time, the table is not displaying. It is displaying 2nd time only.

My code is

```<code>@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getSupportActionBar().hide();
        setContentView(R.layout.activity_aggre_ascendingorder);
        drawerLayout = findViewById(R.id.drawer_layout);
        init();
    }

    @SuppressLint("ResourceType")
    public void init() {
        stk = (TableLayout) findViewById(R.id.table_main);
        TableRow tbrow0 = new TableRow(this);
        TextView tv0 = new TextView(this);
        tv0.setText("Actual Values ");
        tv0.setWidth(330);
        tv0.setGravity(Gravity.CENTER);
        tv0.setTextColor(Color.WHITE);
        tv0.setTextSize(12);
        tv0.setBackgroundResource(R.drawable.border4);
        tbrow0.addView(tv0);
        TextView tv1 = new TextView(this);
        tv1.setText("Meter Values ");
        tv1.setWidth(330);
        tv1.setGravity(Gravity.CENTER);
        tv1.setTextColor(Color.WHITE);
        tv1.setTextSize(12);
        tv1.setBackgroundResource(R.drawable.border4);
        tbrow0.addView(tv1);
        TextView tv2 = new TextView(this);
        tv2.setText("Error ");
        tv2.setWidth(315);
        tv2.setGravity(Gravity.CENTER);
        tv2.setTextColor(Color.WHITE);
        tv2.setTextSize(12);
        tv2.setBackgroundResource(R.drawable.border4);
        tbrow0.addView(tv2);

        Intent z = getIntent();
        input1 = z.getIntExtra(EDIT, 1);
        input2 = z.getIntExtra(TEXT, 1);

        if (input2 == 0) {
            x = 400;
        } else {
            x = input1 / input2;
        }

        stk.addView(tbrow0);
        try {
            for (int i = 0; i < x + 1; i++) {
                TableRow tbrow = new TableRow(this);
                final EditText t1v = new EditText(this);
                t1v.setId(1);
                if (input2 == 0) {
                    t1v.setHint("");
                } else {
                    t1v.setText("" + i * input2);
                }
                final EditText t2v;
                TextView t3v = null;
                t1v.setTextColor(Color.BLACK);
                t1v.setGravity(Gravity.CENTER);
                t1v.setTextSize(12);
                t1v.setInputType(InputType.TYPE_CLASS_NUMBER);
                t1v.setBackgroundResource(R.drawable.border);

                t2v = new EditText(this);
                t2v.setHint("");
                t2v.setTextColor(Color.BLACK);
                t2v.setGravity(Gravity.CENTER);
                t2v.setTextSize(12);
                t2v.setInputType(InputType.TYPE_CLASS_NUMBER);
                t2v.setBackgroundResource(R.drawable.border);

                t3v = new TextView(this);
                t3v.setHint("");
                t3v.setTextColor(Color.BLACK);
                t3v.setGravity(Gravity.CENTER);
                t3v.setTextSize(12);
                t3v.setBackgroundResource(R.drawable.border);

                String stb = "0,0,0";

                if((Integer.parseInt(Prefs.getString("aggasstabLength",""))-1) > i){
                    stb = Prefs.getString("aggasstabVal_" + (i + 1), "");
                }
                //t1v.setText(stb.split(",")[0]);
                t2v.setText(stb.split(",")[1]);
                t3v.setText(stb.split(",")[2]);
                tbrow.addView(t1v);
                tbrow.addView(t2v);
                tbrow.addView(t3v);
                stk.addView(tbrow);
`
</code>```

Can you clear me what is the mistake I am doing on this

ContentLicense: CC BY-SA 3.0

Body:
I am trying to create a layout where I need to add table rows dynamically. Below is the table layout xml

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/displayLinear"
    android:background="@color/background_df"
    android:orientation="vertical" >

         <TableRow
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/display_row"
            android:layout_marginTop="280dip" >

</TableLayout>

The activity file where rows are being added dynamically is

public void init(){
    menuDB = new MenuDBAdapter(this);
    ll = (TableLayout) findViewById(R.id.displayLinear);

    TableRow row=(TableRow)findViewById(R.id.display_row);
    for (int i = 0; i <2; i++) {

        checkBox = new CheckBox(this);
        tv = new TextView(this);
        addBtn = new ImageButton(this);
        addBtn.setImageResource(R.drawable.add);
        minusBtn = new ImageButton(this);
        minusBtn.setImageResource(R.drawable.minus);
        qty = new TextView(this);
        checkBox.setText("hello");
        qty.setText("10");
        row.addView(checkBox);
        row.addView(minusBtn);
        row.addView(qty);
        row.addView(addBtn);
        ll.addView(row,i);

    }
}

But when I run this, I am getting below error

08-13 16:27:46.437: E/AndroidRuntime(23568): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.roms/com.example.roms.DisplayActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

I understand that this is due to command ll.addView(row,i); but when I remove this its adding all stuff in a single row rather tan creating a new row for next item. I tried with giving index too as row.addView(addBtn,i) but still its not populating correctly. Please advise. Thanks.

Body:
I am trying the above code with modification as per my requirement. The table is created properly. Bu the problem is when I am opening the activity 1st time, the table is not displaying. It is displaying 2nd time only.

My code is

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getSupportActionBar().hide();
        setContentView(R.layout.activity_aggre_ascendingorder);
        drawerLayout = findViewById(R.id.drawer_layout);
        init();
    }

    @SuppressLint("ResourceType")
    public void init() {
        stk = (TableLayout) findViewById(R.id.table_main);
        TableRow tbrow0 = new TableRow(this);
        TextView tv0 = new TextView(this);
        tv0.setText("Actual Values ");
        tv0.setWidth(330);
        tv0.setGravity(Gravity.CENTER);
        tv0.setTextColor(Color.WHITE);
        tv0.setTextSize(12);
        tv0.setBackgroundResource(R.drawable.border4);
        tbrow0.addView(tv0);
        TextView tv1 = new TextView(this);
        tv1.setText("Meter Values ");
        tv1.setWidth(330);
        tv1.setGravity(Gravity.CENTER);
        tv1.setTextColor(Color.WHITE);
        tv1.setTextSize(12);
        tv1.setBackgroundResource(R.drawable.border4);
        tbrow0.addView(tv1);
        TextView tv2 = new TextView(this);
        tv2.setText("Error ");
        tv2.setWidth(315);
        tv2.setGravity(Gravity.CENTER);
        tv2.setTextColor(Color.WHITE);
        tv2.setTextSize(12);
        tv2.setBackgroundResource(R.drawable.border4);
        tbrow0.addView(tv2);

        Intent z = getIntent();
        input1 = z.getIntExtra(EDIT, 1);
        input2 = z.getIntExtra(TEXT, 1);

        if (input2 == 0) {
            x = 400;
        } else {
            x = input1 / input2;
        }

        stk.addView(tbrow0);
        try {
            for (int i = 0; i < x + 1; i++) {
                TableRow tbrow = new TableRow(this);
                final EditText t1v = new EditText(this);
                t1v.setId(1);
                if (input2 == 0) {
                    t1v.setHint("");
                } else {
                    t1v.setText("" + i * input2);
                }
                final EditText t2v;
                TextView t3v = null;
                t1v.setTextColor(Color.BLACK);
                t1v.setGravity(Gravity.CENTER);
                t1v.setTextSize(12);
                t1v.setInputType(InputType.TYPE_CLASS_NUMBER);
                t1v.setBackgroundResource(R.drawable.border);

                t2v = new EditText(this);
                t2v.setHint("");
                t2v.setTextColor(Color.BLACK);
                t2v.setGravity(Gravity.CENTER);
                t2v.setTextSize(12);
                t2v.setInputType(InputType.TYPE_CLASS_NUMBER);
                t2v.setBackgroundResource(R.drawable.border);

                t3v = new TextView(this);
                t3v.setHint("");
                t3v.setTextColor(Color.BLACK);
                t3v.setGravity(Gravity.CENTER);
                t3v.setTextSize(12);
                t3v.setBackgroundResource(R.drawable.border);

                String stb = "0,0,0";

                if((Integer.parseInt(Prefs.getString("aggasstabLength",""))-1) > i){
                    stb = Prefs.getString("aggasstabVal_" + (i + 1), "");
                }
                //t1v.setText(stb.split(",")[0]);
                t2v.setText(stb.split(",")[1]);
                t3v.setText(stb.split(",")[2]);
                tbrow.addView(t1v);
                tbrow.addView(t2v);
                tbrow.addView(t3v);
                stk.addView(tbrow);
`

Can you clear me what is the mistake I am doing on this

ContentLicense: CC BY-SA 4.0


问:
Subclass/inherit standard containers?
I often read this statements on Stack Overflow. Personally, I don't find any problem with this, unless I am using it in a polymorphic way; i.e. where I have to use virtual destructor.

If I want to extend/add the functionality of a standard container then what is a better way than inheriting one? Wrapping those container inside a custom class requires much more effort and is still unclean.

答:
There are a number of reasons why this a bad idea.

First, this is a bad idea because the standard containers do not have virtual destructors.  You should never use something polymorphically that does not have virtual destructors, because you cannot guarantee cleanup in your derived class.

Basic rules for virtual dtors

Second, it is really bad design.  And there are actually several reasons it is bad design.  First, you should always extend the functionality of standard containers through algorithms that operate generically.  This is a simple complexity reason - if you have to write an algorithm for every container it applies to and you have M containers and N algorithms, that is M x N methods you must write.  If you write your algorithms generically, you have N algorithms only.  So you get much more reuse.

It is also really bad design because you are breaking a good encapsulation by inheriting from the container.  A good rule of thumb is: if you can perform what you need using the public interface of a type, make that new behavior external to the type.  This improves encapsulation.  If it's a new behavior you want to implement, make it a namespace scope function (like the algorithms).  If you have a new invariant to impose, use containment in a class.

A classic description of encapsulation

Finally, in general, you should never think about inheritance as a means to extend the behavior of a class.  This is one of the big, bad lies of early OOP theory that came about due to unclear thinking about reuse, and it continues to be taught and promoted to this day even though there is a clear theory why it is bad.  When you use inheritance to extend behavior, you are tying that extended behavior to your interface contract in a way that ties users hands to future changes.  For instance, say you have a class of type Socket that communicates using the TCP protocol and you extend it's behavior by deriving a class SSLSocket from Socket and implementing the behavior of the higher SSL stack protocol on top of Socket.  Now, let's say you get a new requirement to have the same protocol of communications, but over a USB line, or over telephony.  You would need to cut and paste all that work to a new class that derives from a USB class, or a Telephony class.  And now, if you find a bug, you have to fix it in all three places, which won't always happen, which means bugs will take longer and not always get fixed...

This is general to any inheritance hierarchy A->B->C->...  When you want to use the behaviors you've extended in derived classes, like B, C, .. on objects not of the base class A, you've got to redesign or you are duplicating implementation.  This leads to very monolithic designs that are very hard to change down the road (think Microsoft's MFC, or their .NET, or - well, they make this mistake a lot).  Instead, you should almost always think of extension through composition whenever possible.  Inheritance should be used when you are thinking "Open / Closed Principle".  You should have abstract base classes and dynamic polymorphism runtime through inherited class, each will full implementations.  Hierarchies shouldn't be deep - almost always two levels.  Only use more than two when you have different dynamic categories that go to a variety of functions that need that distinction for type safety.  In those cases, use abstract bases until the leaf classes, which have the implementation.

Title: Subclass/inherit standard containers?


问:
Is it possible to separate part of a match in RegEx within RegEx?
So I've come across an issue while using RegEx.

As typical, my code is often, just, an absolute mess! I realized I could probably clean it up with RegEx.

So I went on to make a Minecraft color formatter for a stupid project of mine, which is a completely custom server software that is based on TypeScript.

As I was making it, I soon realized, that the way I did it - guess what! Doesn't work. It only returns one match. Here's an example of what I get:

```<code>String: &#ff5c5chello there! this is just a &#aa5cfftest!
Matches: [ "&#ff5c5chello there! this is just a &#aa5cfftest!" ]
</code>```

And what I expect is:

```<code>String: &#ff5c5chello there! this is just a &#aa5cfftest!
Matches: [ "&#ff5c5chello there! this is just a", "&#aa5cfftest!" ]
</code>```

If it isn't clear, what I want to separate off is &#(hex code), as an example: &#ffffff

The regex I used is /(&#[0-9a-f]{6}.*)*/g

Does anyone know how to do this? Or is this even possible with RegEx?

Edit: Another thing that I must mention is that the start, if it doesn't start with something like &#(hex code), must be another separate match! Example:

```<code>String: I am the &#5cff5cComputer &#4cee4cMan
Matches: [ "I am the ", "&#5cff5cComputer ", "&#4cee4cMan" ]
</code>```

答:
I believe this is what you want:

```<code>.+?(?=(?:&#|$))
</code>```

You can play with it and have an explanation of how it works in the following link: https://regex101.com/r/vBUSi9/1

Body:
So I've come across an issue while using RegEx.

As typical, my code is often, just, an absolute mess! I realized I could probably clean it up with RegEx.

So I went on to make a Minecraft color formatter for a stupid project of mine, which is a completely custom server software that is based on TypeScript.

As I was making it, I soon realized, that the way I did it - guess what! Doesn't work. It only returns one match. Here's an example of what I get:

String: &#ff5c5chello there! this is just a &#aa5cfftest!
Matches: [ "&#ff5c5chello there! this is just a &#aa5cfftest!" ]

And what I expect is:

String: &#ff5c5chello there! this is just a &#aa5cfftest!
Matches: [ "&#ff5c5chello there! this is just a", "&#aa5cfftest!" ]

If it isn't clear, what I want to separate off is &#(hex code), as an example: &#ffffff

The regex I used is /(&#[0-9a-f]{6}.*)*/g

Does anyone know how to do this? Or is this even possible with RegEx?

Edit: Another thing that I must mention is that the start, if it doesn't start with something like &#(hex code), must be another separate match! Example:

String: I am the &#5cff5cComputer &#4cee4cMan
Matches: [ "I am the ", "&#5cff5cComputer ", "&#4cee4cMan" ]

Body:
I believe this is what you want:

.+?(?=(?:&#|$))

You can play with it and have an explanation of how it works in the following link: https://regex101.com/r/vBUSi9/1


问:
[linphone-sdk ios]Getting Error No such module 'linphonesw'
We are using compiled linphone sdk.Integrate compiled sdk in our project but getting below error "No such module 'linphonesw'.
linphonesw folder created but how to add in our project.
we are using linphone-sdk 4.4.2 and linphone-iPhone project 4.2.2.
please help us to resolve this error.
PFA.
Thank you.
[]

答:
i have same issue,any new solution?

I installed linphone sdk osx using Pods With the following command in the Pod file

pod 'linphone-sdk', '5.0.69', :source => ‘https://gitlab.linphone.org/BC/public/podspec-macos.git'
After executing command pod install and installing successfully Gives this error for import linphonesw

No such module 'linphonesw'


问:
Why this happens
```<code>my_variable_name = str("John")
print(my_variable_name)
</code>```

This is the code for example, now if I happen to add the double quotes around "my_variable_name" in this statement:

```<code>print(my_variable_name)
</code>```

It just simply display whatever is written inside the "" but if I don't add it'll print "john". Now what I think the reason is because when compiler find something inside "" that tells it to display whatever datatype it is while without "" it just displays the stored or u can say assigned value . I know its easy (basis) but I do this like all the time and my knowledge about this problem never satisfies me

答:
The problem has nothing to do with print function.

"my_variable_name" is a string literal. Single or triple quotes could also be used.

my_variable_name is a reference to a previously defined variable of that name. The type of the variable's value could be anything.

You can print any object, and it'll return the str() representation of it.

Unrelated, you don't need str() function to define a string literal.

when compiler find something inside "" that tells it to display whatever datatype it is

Python is an interpreted language, it's not the compiler doing this. The datatype of anything enclosed in quotes is always a string

Title: Why this happens

Body:
my_variable_name = str("John")
print(my_variable_name)

This is the code for example, now if I happen to add the double quotes around "my_variable_name" in this statement:

print(my_variable_name)

It just simply display whatever is written inside the "" but if I don't add it'll print "john". Now what I think the reason is because when compiler find something inside "" that tells it to display whatever datatype it is while without "" it just displays the stored or u can say assigned value . I know its easy (basis) but I do this like all the time and my knowledge about this problem never satisfies me


问:
How Does An Operating System Introduces The C Language To Write The Kernel
Does this introduction occurs at the NTLDR stage because it must be introduce, I mean isn't the Kernel written in C? I thought a computers only "known-before" programming language was Assembly Language that is hard coded at the Microcode of the Processor?</p>

答:
C is a compiled language, as opposed to an interpreted language. C programs as well as the C runtime library are compiled into machine code, so they don't need any kind of runtime environment such as an interpreter or virtual machine to be loaded in order to execute.

The entry point of a compiled program (including a kernel) will call into its runtime library and perform any initialization required before executing the program, but this is all machine code.


问:
React Native Firebase onAuthStateChanged returns user after signOut
I'm struggling with signing out in my app. I'm using freshly installed managed Expo app with dev-client and @react-natice-firebase/auth, all in their current version. For the user state i'm using Recoil. Sign in works just fine, the problem occurs when signing out. Here is my AuthProvider.ts

```<code>import React, { FC, Fragment, useEffect } from 'react';

import auth, { FirebaseAuthTypes } from '@react-native-firebase/auth';
import { useSetRecoilState } from 'recoil';

import { firebaseUser } from '../../../state/user/atoms/firebaseUser';

export const AuthProvider: FC = ({ children }) => {
  const setUser = useSetRecoilState(firebaseUser);
  const onAuthStateChanged = (user: FirebaseAuthTypes.User | null) => setUser(user);

  useEffect(() => {
    const subscriber = auth().onAuthStateChanged(onAuthStateChanged);

    return subscriber;
  }, []);

  return <Fragment children={children} />;
};
</code>```

And the function I use to sign out:

```<code>const logout = () => async () => await auth().signOut()

<MainButton action={logout()} label={'Logout'} />
</code>```

After sign in the onAuthStateChanged listener returns user object, but after hitting 'Logout' button it returns the user object again instead of null and the interface doesn't update. After hitting it again, console returns an error:

[Unhandled promise rejection: Error: [auth/no-current-user] No user currently signed in.]

onAuthStateChanged is not called again, user state persists and the interface doesn't update.

User state is cleared after restarting the app and the sign in works just fine again. The behaviour is similar when switching users (eg. from anonymous to signed in).

答: Maybe someone will face the same problem in the future, so here's what was causing it. It wa Recoil, apparently the two libraries don't work well together, so I've rewritten it using context and works just fine.</p>

Body:
I'm struggling with signing out in my app. I'm using freshly installed managed Expo app with dev-client and @react-natice-firebase/auth, all in their current version. For the user state i'm using Recoil. Sign in works just fine, the problem occurs when signing out. Here is my AuthProvider.ts

import React, { FC, Fragment, useEffect } from 'react';

import auth, { FirebaseAuthTypes } from '@react-native-firebase/auth';
import { useSetRecoilState } from 'recoil';

import { firebaseUser } from '../../../state/user/atoms/firebaseUser';

export const AuthProvider: FC = ({ children }) => {
  const setUser = useSetRecoilState(firebaseUser);
  const onAuthStateChanged = (user: FirebaseAuthTypes.User | null) => setUser(user);

  useEffect(() => {
    const subscriber = auth().onAuthStateChanged(onAuthStateChanged);

    return subscriber;
  }, []);

  return <Fragment children={children} />;
};

And the function I use to sign out:

const logout = () => async () => await auth().signOut()

<MainButton action={logout()} label={'Logout'} />

After sign in the onAuthStateChanged listener returns user object, but after hitting 'Logout' button it returns the user object again instead of null and the interface doesn't update. After hitting it again, console returns an error:

[Unhandled promise rejection: Error: [auth/no-current-user] No user currently signed in.]

onAuthStateChanged is not called again, user state persists and the interface doesn't update.

User state is cleared after restarting the app and the sign in works just fine again. The behaviour is similar when switching users (eg. from anonymous to signed in).


问:
Angular.js: Cannot set a custom attribute directive
I have ultra-simple code with a directive and a component trying to use it but the code doesn't work. Cannot understand what I am doing wrong.

@Directive({
  selector: '[classSetter]'
})
class classSetter implements OnInit {

  @Input() classSetter : string = "";

  el : ElementRef;

  constructor (el : ElementRef) {
    this.el = el;
  }

  ngOnInit () {
    this.el.nativeElement.classList.add(this.classSetter);
  }
}

@Component({
  selector: 'app-root',
  styles: ['.blue {background-color: blue;}'],
  template: `
              {{title}}
            `
})
export class AppComponent {
  title = 'directive';
}```

The error I get is Can't bind to 'classSetter' since it isn't a known property of 'span'.

StackBlitz: https://stackblitz.com/edit/angular-ivy-gf1ee4

Please, tell me, what do I miss here?

答:
The directive needs to go in declarations array of module not the providers array of component decorator. fixed it here as well :-

https://stackblitz.com/edit/angular-ivy-bz2sez?file=src/app/app.component.ts

Body:
I have ultra-simple code with a directive and a component trying to use it but the code doesn't work. Cannot understand what I am doing wrong.

@Directive({
  selector: '[classSetter]'
})
class classSetter implements OnInit {

  @Input() classSetter : string = "";

  el : ElementRef;

  constructor (el : ElementRef) {
    this.el = el;
  }

  ngOnInit () {
    this.el.nativeElement.classList.add(this.classSetter);
  }
}

@Component({
  selector: 'app-root',
  styles: ['.blue {background-color: blue;}'],
  template: `
              {{title}}
            `
})
export class AppComponent {
  title = 'directive';
}

The error I get is Can't bind to 'classSetter' since it isn't a known property of 'span'.

StackBlitz: https://stackblitz.com/edit/angular-ivy-gf1ee4

Please, tell me, what do I miss here?


问:
How can I split strings so that only numbers are selected?

please excuse me for the change in this question

I want to split a string (e.g. text1, text2), so that only numbers are output:

I tried the following:

```<code>import re

# example text1

text1 = " climb   -  95/ 85     0.18   low     -  4680"

split_text1 = re.split(" +", text1)

print(split_text1)

['', 'climb', '-', '95/', '85', '0.18', 'low', '-', '4680']

# example text2

text2 = "CD 3 TO   F TO GD   .80000E+02   .00000E+00   .00000E+00   .00000E+00 /"

split_text2 = re.split(" +", text2)

print(split_text2)

['CD 3 TO', 'F TO GD', '.80000E+02', '.00000E+00', '.00000E+00', '.00000E+00 /']
</code>```

How can I get as result:

```<code># split_text1 = ['95', '85', '0.18', '4680']

# split_text2 = ['3', '80.0','0.0', '0.0', 0.0]
</code>```

答:
You could use findall to get the numeric patterns and convert the strings to float or int:

```<code>import re
def getNums(S):
    pattern = r"[+-]?(?:[0-9]+\.?[0-9]*|\.[0-9]+)(?:[Ee][+-]?[0-9]+)?"
    result = []
    for part in re.findall(pattern,S):
        try:
            result.append(float(part))
            result[-1] = int(part)
        except ValueError:pass
    return result

text = " climb   -  95/ 85     0.18   low     -  4680"
print(getNums(text))
# [95, 85, 0.18, 4680]

text2 = "CD 3 TO   F TO GD   .80000E+02   .00000E+00   .00000E+00   .00000E+00 /"#
print(getNums(text2))
# [3, 80.0, 0.0, 0.0, 0.0]
</code>```

I'm assuming you want the output to be all numeric values rather than a mix of reformatted strings and numerics

Here's a breakdown of the expression:

[+-]? Optional leading sign

(?:[0-9]+\.?[0-9]*|\.[0-9]+) Mandatory central part (non-capturing group)

...|... either start with a digit or with a decimal point

[0-9]+\.?[0-9]* start with digit(s) with optional decimal point and optional fractional digits

\.[0-9]+start with a decimal point followed by one or more digits (i.e. a decimal point without digits on the left or right is not a number.)

(?:[Ee][+-][0-9]+)? Optional exponent part (non-capturing group)

E oe e to indicate start of exponent part

[+-]? optional sign of exponent

[0-9]+ mandatory exponent digits

Body:
please excuse me for the change in this question

I want to split a string (e.g. text1, text2), so that only numbers are output:

I tried the following:

import re

# example text1

text1 = " climb   -  95/ 85     0.18   low     -  4680"

split_text1 = re.split(" +", text1)

print(split_text1)

['', 'climb', '-', '95/', '85', '0.18', 'low', '-', '4680']

# example text2

text2 = "CD 3 TO   F TO GD   .80000E+02   .00000E+00   .00000E+00   .00000E+00 /"

split_text2 = re.split(" +", text2)

print(split_text2)

['CD 3 TO', 'F TO GD', '.80000E+02', '.00000E+00', '.00000E+00', '.00000E+00 /']

How can I get as result:

# split_text1 = ['95', '85', '0.18', '4680']

# split_text2 = ['3', '80.0','0.0', '0.0', 0.0]

Body:
You could use findall to get the numeric patterns and convert the strings to float or int:

import re
def getNums(S):
    pattern = r"[+-]?(?:[0-9]+\.?[0-9]*|\.[0-9]+)(?:[Ee][+-]?[0-9]+)?"
    result = []
    for part in re.findall(pattern,S):
        try:
            result.append(float(part))
            result[-1] = int(part)
        except ValueError:pass
    return result

text = " climb   -  95/ 85     0.18   low     -  4680"
print(getNums(text))
# [95, 85, 0.18, 4680]

text2 = "CD 3 TO   F TO GD   .80000E+02   .00000E+00   .00000E+00   .00000E+00 /"#
print(getNums(text2))
# [3, 80.0, 0.0, 0.0, 0.0]

I'm assuming you want the output to be all numeric values rather than a mix of reformatted strings and numerics

Here's a breakdown of the expression:

[+-]? Optional leading sign

(?:[0-9]+\.?[0-9]*|\.[0-9]+) Mandatory central part (non-capturing group)

...|... either start with a digit or with a decimal point

[0-9]+\.?[0-9]* start with digit(s) with optional decimal point and optional fractional digits

\.[0-9]+start with a decimal point followed by one or more digits (i.e. a decimal point without digits on the left or right is not a number.)

(?:[Ee][+-][0-9]+)? Optional exponent part (non-capturing group)

E oe e to indicate start of exponent part

[+-]? optional sign of exponent

[0-9]+ mandatory exponent digits


问:
Gitbook-cli install error TypeError: cb.apply is not a function inside graceful-fs
When executing any gitbook command in the terminal, the following error is thrown:

```<code>/home/travis/.nvm/versions/node/v12.18.3/lib/node_modules/gitbook-cli/node_modules/npm/node_modules/graceful-fs/polyfills.js:287
      if (cb) cb.apply(this, arguments)
                 ^
TypeError: cb.apply is not a function
    at /home/travis/.nvm/versions/node/v12.18.3/lib/node_modules/gitbook-cli/node_modules/npm/node_modules/graceful-fs/polyfills.js:287:18
    at FSReqCallback.oncomplete (fs.js:169:5)
</code>```

NOTE: This does not happen in node version v12.18.2 and is still happening in version v14.6.0

The gitbook-cli seems to not be working right now, failing because of their outdated graceful-fs dependency.

Any ideas how to fix this?

答:
This worked for me:

```<code>npm install graceful-fs@latest --save
</code>```

Then re-run:

```<code>npm install -g gitbook-cli
</code>```

UPDATE =====
Another option would be to use NVM and install node v12.8.2.

Use this https://github.com/nvm-sh/nvm.

Body:
When executing any gitbook command in the terminal, the following error is thrown:

/home/travis/.nvm/versions/node/v12.18.3/lib/node_modules/gitbook-cli/node_modules/npm/node_modules/graceful-fs/polyfills.js:287
      if (cb) cb.apply(this, arguments)
                 ^
TypeError: cb.apply is not a function
    at /home/travis/.nvm/versions/node/v12.18.3/lib/node_modules/gitbook-cli/node_modules/npm/node_modules/graceful-fs/polyfills.js:287:18
    at FSReqCallback.oncomplete (fs.js:169:5)

NOTE: This does not happen in node version v12.18.2 and is still happening in version v14.6.0

The gitbook-cli seems to not be working right now, failing because of their outdated graceful-fs dependency.

Any ideas how to fix this?

Body:
This worked for me:

npm install graceful-fs@latest --save

Then re-run:

npm install -g gitbook-cli

UPDATE =====
Another option would be to use NVM and install node v12.8.2.

Use this https://github.com/nvm-sh/nvm.


问:
can't access class in same package
```<code>Project directory:
 Project
 -[other directories]
 -bin
 --A.java
 --B.java
</code>```

Class A source code:

```<code>package bin;
public class A{
 public static void main(String[] args){
  B use=new B("Hello");
  use.run();
 }
}
</code>```

Class B source code:

```<code>package bin;
public class B{
 static String x=null;
 public B(String text){
  x=text;
 }
 public static void run(){
  System.out.println(x);
 }
}
</code>```

There was no error when I compiled B.java, when I tried to compile A.java, I got:

```<code>A.java:4: error: cannot find symbol
     B use=new B("Hello");
  symbol:   class B
  location: class A
search.java:4: error: cannot find symbol
     B use=new B("Hello");
           ^
  symbol:   class B
  location: class A
</code>```

By the way, I am not using an IDE to compile this, I just edited the files with Geany and nano, then tried to compile them from the terminal with javac.

答:
Assuming the current working directory is Project, the code shold be compiled as:

```<code>Project> java bin/*.java
</code>```

This compiles all classes in bin into the same directory:

```<code>Project> dir bin
13.02.2022  18:20    <DIR>          .
13.02.2022  18:20    <DIR>          ..
13.02.2022  18:20               346 A.class
13.02.2022  18:14               117 A.java
13.02.2022  18:20               478 B.class
13.02.2022  18:14               154 B.java
               4 files          1 095 bytes
</code>```

Run the code providing the package name in the class bin.A:

```<code>Project> java bin.A
Hello
</code>```

However, to avoid mess in the source folder bin where the .class files are created by the compiler along with the .java source files, it would be better to provide a separate directory (e.g. classes) and refer it providing classpath parameter -cp:

```<code>Project>javac -d classes bin/*.java

Project>java -cp classes bin.A
Hello
</code>```

Title: can't access class in same package

Body:
Project directory:
 Project
 -[other directories]
 -bin
 --A.java
 --B.java

Class A source code:

package bin;
public class A{
 public static void main(String[] args){
  B use=new B("Hello");
  use.run();
 }
}

Class B source code:

package bin;
public class B{
 static String x=null;
 public B(String text){
  x=text;
 }
 public static void run(){
  System.out.println(x);
 }
}

There was no error when I compiled B.java, when I tried to compile A.java, I got:

A.java:4: error: cannot find symbol
     B use=new B("Hello");
  symbol:   class B
  location: class A
search.java:4: error: cannot find symbol
     B use=new B("Hello");
           ^
  symbol:   class B
  location: class A

By the way, I am not using an IDE to compile this, I just edited the files with Geany and nano, then tried to compile them from the terminal with javac.

Body:
Assuming the current working directory is Project, the code shold be compiled as:

Project> java bin/*.java

This compiles all classes in bin into the same directory:

Project> dir bin
13.02.2022  18:20    <DIR>          .
13.02.2022  18:20    <DIR>          ..
13.02.2022  18:20               346 A.class
13.02.2022  18:14               117 A.java
13.02.2022  18:20               478 B.class
13.02.2022  18:14               154 B.java
               4 files          1 095 bytes

Run the code providing the package name in the class bin.A:

Project> java bin.A
Hello

However, to avoid mess in the source folder bin where the .class files are created by the compiler along with the .java source files, it would be better to provide a separate directory (e.g. classes) and refer it providing classpath parameter -cp:

Project>javac -d classes bin/*.java

Project>java -cp classes bin.A
Hello


问:
std::vectors to arrow::table
I've looked through the Apache Arrow docs but I can't find a clean way of converting equal length std::vectors into an arrow::Array and then an arrow::Table. Here's the code in question.

```<code>#include <vector>
#include <arrow/array.h>
#include <arrow/table.h>

const std::vector<double> a = {1,2,3,4,5};
const std::vector<bool> b = {true, false, false, true, true};

auto schema = arrow::schema({arrow::field("a", arrow::float64()), arrow::field("b", arrow::boolean())});

std::shared_ptr<arrow::Array> array_a(N, arrow::float64());
std::shared_ptr<arrow::Array> array_b(N, arrow::boolean());

// how to store the contents of the vectors a and b into array_a and array_b, resp.
// ...?

std::shared_ptr<arrow::Table> table = arrow::Table::Make(schema, {array_a, array_b});
</code>```

答:
As mentioned in the documentation,you can use a builder for this:

const std::vector<double> a = {1,2,3,4,5};
const std::vector<bool> b = {true, false, false, true, true};

auto schema = arrow::schema({arrow::field("a", arrow::float64()), arrow::field("b", arrow::boolean())});

arrow::DoubleBuilder aBuilder;
PARQUET_THROW_NOT_OK(aBuilder.AppendValues(a));

arrow::BooleanBuilder bBuilder;
PARQUET_THROW_NOT_OK(bBuilder.AppendValues(b));

std::shared_ptr<arrow::Array> array_a, array_b;
ARROW_ASSIGN_OR_RAISE(array_a, aBuilder.Finish());
ARROW_ASSIGN_OR_RAISE(array_b, bBuilder.Finish());

std::shared_ptr<arrow::Table> table = arrow::Table::Make(schema, {array_a, array_b});
```

Title: std::vectors to arrow::table

Body:
I've looked through the Apache Arrow docs but I can't find a clean way of converting equal length std::vectors into an arrow::Array and then an arrow::Table. Here's the code in question.

#include <vector>
#include <arrow/array.h>
#include <arrow/table.h>

const std::vector<double> a = {1,2,3,4,5};
const std::vector<bool> b = {true, false, false, true, true};

auto schema = arrow::schema({arrow::field("a", arrow::float64()), arrow::field("b", arrow::boolean())});

std::shared_ptr<arrow::Array> array_a(N, arrow::float64());
std::shared_ptr<arrow::Array> array_b(N, arrow::boolean());

// how to store the contents of the vectors a and b into array_a and array_b, resp.
// ...?

std::shared_ptr<arrow::Table> table = arrow::Table::Make(schema, {array_a, array_b});


问:
R adding a new column in a data frame by recursivly filling 1:3 value based on another column
I have a dataframe, e.g.:

```<code>df <- data.frame(Group = rep(c("A", "B", "C"),  times = c(4, 4, 6))
> df
   Group
1      A
2      A
3      B
4      B
5      B
6      B
7      C
8      C
9      C
10     C
11     C
12     C
</code>```

I want to add a new column Type by recursively filling value 1:3 based on the Group column.

The resulting DF is like

```<code>> df2
   Group Type
1      A    1
2      A    2
3      B    1
4      B    2
5      B    3
6      B    1
7      C    1
8      C    2
9      C    3
10     C    1
11     C    2
12     C    3
</code>```

I don't know how to achieve this. Thanks a lot for your help

答:
Using rowid from data.table

```<code>library(data.table)
setDT(df)[, Type := rowid(gl(.N, 3, .N)), Group]
</code>```

-output

```<code>> df
     Group  Type
    <char> <int>
 1:      A     1
 2:      A     2
 3:      A     3
 4:      A     1
 5:      B     1
 6:      B     2
 7:      B     3
 8:      B     1
 9:      C     1
10:      C     2
11:      C     3
12:      C     1
13:      C     2
14:      C     3
</code>```

Body:
I have a dataframe, e.g.:

df <- data.frame(Group = rep(c("A", "B", "C"),  times = c(4, 4, 6))
> df
   Group
1      A
2      A
3      B
4      B
5      B
6      B
7      C
8      C
9      C
10     C
11     C
12     C

I want to add a new column Type by recursively filling value 1:3 based on the Group column.

The resulting DF is like

> df2
   Group Type
1      A    1
2      A    2
3      B    1
4      B    2
5      B    3
6      B    1
7      C    1
8      C    2
9      C    3
10     C    1
11     C    2
12     C    3

I don't know how to achieve this. Thanks a lot for your help

Body:
Using rowid from data.table

library(data.table)
setDT(df)[, Type := rowid(gl(.N, 3, .N)), Group]

-output

> df
     Group  Type
    <char> <int>
 1:      A     1
 2:      A     2
 3:      A     3
 4:      A     1
 5:      B     1
 6:      B     2
 7:      B     3
 8:      B     1
 9:      C     1
10:      C     2
11:      C     3
12:      C     1
13:      C     2
14:      C     3


问:
Installing a VM with Ubuntu 16 on m1 macbook air
I have an M1 MacBook air and hence I need OS images supporting ARM. I need to use Ubuntu 14 or 16 on VM for an important task. I have tried using Parallel Desktop's free trial. It works fine for the Ubuntu 20 (ARM) image (.iso) but when I try to start running VM with ubnutu 16 ARM image (from this page), it is stuck at the following stage (see the image), I think there is probably some problem with the OS image.
Can anybody help me with running Ubuntu 16 (ARM) on a VM on my laptop?</p>

答: You can try UTM and emulate the 16.04 x86_64, but it will be very slow.</p>


问:
Multiple Trips to the Db
I have those group of CheckBox Lists and Repeaters (about 8 controls needed to be loaded from my db) and for each control, I have a method in my DataAccess Layer to select the information and get it back to my control.

But There's a page that I need all those 8 controls to be loaded on the same time .. so each method will be a trip to the db and I understand that's what affects the performance. So can I have like a new method to create the connection and open it, then I can call multiple methods to access the db and load the info then close the connection at the end.

Any ideas if those 8 connections are okay for performance ? and what do you think about this idea and how can it be applied in a practical way ?

答: There is very little overhead when you open and close a connection, so you should not worry about that.</p>

Title: Multiple Trips to the Db


问:
Puppeteer Cluster Inconsistent Results
I've recently converted a script over from Puppeteer to Puppeteer Cluster and during testing I've observed some odd results when testing multiple pages concurrently.

Effectively I'm loading a single page and then iterating over the product options on the page and gathering the price for any product variants.

One particular product has around 9 product variants, sometimes I will accurately capture all 9 variants, whereas on the next testing cycle it may only return 2 or 3 variants.

Any help would be greatly appreciated!

```<code>const puppeteer = require('puppeteer');
const { Cluster } = require('puppeteer-cluster');

const Product = require('../utils/product')

const config = require('../config/config.json')
const selectors = config.productData;

(async () => {

    const urls = [
        {link: ...},
        {link: ...},
        {link: ...}
    ]

    const cluster = await Cluster.launch({
        concurrency: Cluster.CONCURRENCY_CONTEXT,
        maxConcurrency: 5,
        puppeteerOptions: {
          headless: false
        },
    });

    await cluster.task(async ({ page, data: url }) => {

        //instantiate a new product object
        const product = new Product();

        await page.goto(url, { waitUntil: 'load' });

        const skuprice = await page.$eval(selectors.price, element => element.innerText);

        console.log('Sku Price:' + skuprice)

        //deal with variants
        const options = await page.$$eval(selectors.variant, elements => elements.map(element=>element.id))

        if (options.length > 0) {

            //set up a variants array
            for (let index = 0; index < options.length; index++) {

                const element = options[index];

                await page.waitForSelector(`#${element}`);
                await page.$eval(`#${element}`, radio => radio.click());
                await page.waitForTimeout(500);

                const variantprice = await page.$eval(selectors.price, element => element.innerText);

                console.log('Variant Price:' + variantprice)

            }

        }

    });

    urls.forEach(url => {
        cluster.queue(url.link);
    })

    // many more pages
    await cluster.idle();
    await cluster.close();

})();
</code>```

答:
Dynamic javascript page should be scraped when all of the element is visible.

You can do following tricks:

[1] wait until selector is visible, check with
await page.waitForSelector(selector, {visible: true, timeout: 0})

[2] wait for desired time, but this is more flaky and prone to resulting error.

You can simplify and rewrite your code, like this:

```<code>await page.waitForSelector(`#${element}`, {visible: true, timeout: 0})
await page.click(`#${element}`)
/* await page.waitForTimeout(500) <= prone to error, use line below */
await page.waitForSelector(selectors.price, {visible: true, timeout: 0})
const variantprice = await page.$eval(selectors.price, element => element.innerText)
</code>```

Title: Puppeteer Cluster Inconsistent Results

Body:
I've recently converted a script over from Puppeteer to Puppeteer Cluster and during testing I've observed some odd results when testing multiple pages concurrently.

Effectively I'm loading a single page and then iterating over the product options on the page and gathering the price for any product variants.

One particular product has around 9 product variants, sometimes I will accurately capture all 9 variants, whereas on the next testing cycle it may only return 2 or 3 variants.

Any help would be greatly appreciated!

const puppeteer = require('puppeteer');
const { Cluster } = require('puppeteer-cluster');

const Product = require('../utils/product')

const config = require('../config/config.json')
const selectors = config.productData;

(async () => {

    const urls = [
        {link: ...},
        {link: ...},
        {link: ...}
    ]

    const cluster = await Cluster.launch({
        concurrency: Cluster.CONCURRENCY_CONTEXT,
        maxConcurrency: 5,
        puppeteerOptions: {
          headless: false
        },
    });

    await cluster.task(async ({ page, data: url }) => {

        //instantiate a new product object
        const product = new Product();

        await page.goto(url, { waitUntil: 'load' });

        const skuprice = await page.$eval(selectors.price, element => element.innerText);

        console.log('Sku Price:' + skuprice)

        //deal with variants
        const options = await page.$$eval(selectors.variant, elements => elements.map(element=>element.id))

        if (options.length > 0) {

            //set up a variants array
            for (let index = 0; index < options.length; index++) {

                const element = options[index];

                await page.waitForSelector(`#${element}`);
                await page.$eval(`#${element}`, radio => radio.click());
                await page.waitForTimeout(500);

                const variantprice = await page.$eval(selectors.price, element => element.innerText);

                console.log('Variant Price:' + variantprice)

            }

        }

    });

    urls.forEach(url => {
        cluster.queue(url.link);
    })

    // many more pages
    await cluster.idle();
    await cluster.close();

})();

Body:
Dynamic javascript page should be scraped when all of the element is visible.

You can do following tricks:

[1] wait until selector is visible, check with
await page.waitForSelector(selector, {visible: true, timeout: 0})

[2] wait for desired time, but this is more flaky and prone to resulting error.

You can simplify and rewrite your code, like this:

await page.waitForSelector(`#${element}`, {visible: true, timeout: 0})
await page.click(`#${element}`)
/* await page.waitForTimeout(500) <= prone to error, use line below */
await page.waitForSelector(selectors.price, {visible: true, timeout: 0})
const variantprice = await page.$eval(selectors.price, element => element.innerText)


问:
IPv6 zero compression
When using zero-compression on the following IPv6 address

```<code>2001:0DB8:0000:CD30:0000:0000:0000:0000/60
</code>```

Why is this not correct:

```<code>2001:DB8::CD30::/60
</code>```

... while this is:

```<code>2001:DB8:0:CD30::/60
</code>```

答:
The reason is that :: is used to shorten multiple zeros in the 16-bit address field.

In your example 2001:0DB8:0000:CD30:0000:0000:0000:0000/60, it only has multiple 0s in the 16-bit field at the suffix, the 0000 in 2001:0DB8:0000:CD30: is just one 16-bit field and you'd just use 0 to shorten it.

More interesting question: How would you shorten this2001:0000:0000:CD30:0000:0000:0000:0000/60?

It is defined in the standard:

In addition, Section 2.2 of [RFC4291] notes,

```<code>  'The "::" can only appear once in an address.'
</code>```

What it means that the address can be written as either:
2001:0:0:CD30::/60 OR 2001::0:CD30:0:0:0:0/60.

Both are valid, but I'd prefer the first representation since the purpose of zeroco mpression is to shorten the address where the first representation is shorter.

Title: IPv6 zero compression

Body:
When using zero-compression on the following IPv6 address

2001:0DB8:0000:CD30:0000:0000:0000:0000/60

Why is this not correct:

2001:DB8::CD30::/60

... while this is:

2001:DB8:0:CD30::/60

Body:
The reason is that :: is used to shorten multiple zeros in the 16-bit address field.

In your example 2001:0DB8:0000:CD30:0000:0000:0000:0000/60, it only has multiple 0s in the 16-bit field at the suffix, the 0000 in 2001:0DB8:0000:CD30: is just one 16-bit field and you'd just use 0 to shorten it.

More interesting question: How would you shorten this2001:0000:0000:CD30:0000:0000:0000:0000/60?

It is defined in the standard:

In addition, Section 2.2 of [RFC4291] notes,

  'The "::" can only appear once in an address.'

What it means that the address can be written as either:
2001:0:0:CD30::/60 OR 2001::0:CD30:0:0:0:0/60.

Both are valid, but I'd prefer the first representation since the purpose of zeroco mpression is to shorten the address where the first representation is shorter.


问:
Does hibernate set back reference in @OneToMany @ManyToOne relationship automatically?
I have Order entity that has orderItems list.

```<code>@OneToMany(mappedBy ="order")
List<OrderItem> orderItems;
</code>```

OrderItem has back reference to Order

```<code>@ManyToOne
Order order;
</code>```

When I save Order should I manually set backreference in OrderItem entity?
Like this

```<code>OrderItem orderItem1 = new OrderItem( //constructor );
OrderItem orderItem2 = new OrderItem( //constructor );
List orderItems = Arrays.asList(orderItem1, orderItem2);
Order order = new Order( orderItems);

orderItems.forEach(orderItem -> orderItem.setOrder(order); // like this?
</code>```

Do Hibernate and Spring data jpa set it automatically?

答:
For creating and updating case , they will not help you to set it automatically and you have to configure the relationship by yourself.

The mappedBy here is to define whether Order.orderItems or OrderItem.order is to used to provide the value for the corresponding DB column that link between them. (i.e. order_id column in order_item table).

If mappedBy is defined , OrderItem.order will be used to provide the value for the relationship. Otherwise , Order.orderItems will be used.

For the loading case , it will help you to set it automatically.

Body:
I have Order entity that has orderItems list.

@OneToMany(mappedBy ="order")
List<OrderItem> orderItems;

OrderItem has back reference to Order

@ManyToOne
Order order;

When I save Order should I manually set backreference in OrderItem entity?
Like this

OrderItem orderItem1 = new OrderItem( //constructor );
OrderItem orderItem2 = new OrderItem( //constructor );
List orderItems = Arrays.asList(orderItem1, orderItem2);
Order order = new Order( orderItems);

orderItems.forEach(orderItem -> orderItem.setOrder(order); // like this?

Do Hibernate and Spring data jpa set it automatically?