问:
Appium application is giving null pointer exception if using two or more classes in testng.xml
Appium application is giving null pointer exception if using two or more classes in testng.xml
Attached are the codes below. If I use any one of the class in testng.xml file, it works fine. But if I define both the classes in testng.xml file, it gives null pointer exception. Please help...
Application driver class :

```<code>package wikipedia_app_setup;

import java.net.URL;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;

public class Wikipedia_app_launch {
    //public static AppiumDriver<MobileElement> driver;
    public WebDriver driver;

    @BeforeSuite
    public WebDriver openWikipedia() throws Exception
    {
        DesiredCapabilities dc=new DesiredCapabilities();
        dc.setCapability("deviceName", "Moto g5 plus");
        dc.setCapability("udid","ZY223XXDVV");
        dc.setCapability("platformName","Android");
        dc.setCapability("platformVersion","8.1.0");
        dc.setCapability("app","C:\\Users\\Keshavgoyal\\Downloads\\org.wikipedia.apk");
/*      dc.setCapability("appPackage","com.google.android.calculator");
        dc.setCapability("appActivity","com.android.calculator2.Calculator");*/
        URL url=new URL("http://127.0.0.1:4723/wd/hub");
        driver=new AppiumDriver<MobileElement>(url,dc);
        System.out.println("Application Started");
        Thread.sleep(10000);

    return driver;
}

    @AfterSuite
    public void closeWikipedia() throws Exception
    {
        driver.quit();
}
}

</code>```

First class locators class :

```<code>package wikipedia_login_page;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

import junit.framework.Assert;

public class Login_test_elements  {

    //public AppiumDriver<WebElement> driver;

    public WebDriver driver;
    public final String wrongCredentialMessage = "Incorrect username or password entered";

    // Form Elements
    @FindBy(id ="org.wikipedia:id/menu_overflow_button")
    public WebElement menuOverflowButton;
    @FindBy(id = "org.wikipedia:id/explore_overflow_account_container")
    public WebElement logOnButton;
    @FindBy(id = "org.wikipedia:id/login_username_text")
    public WebElement usernameTextbox;
    @FindBy(xpath = "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[2]/android.widget.FrameLayout/android.widget.ScrollView/android.widget.LinearLayout/TextInputLayout[2]/android.widget.FrameLayout/android.widget.EditText")
    public WebElement passwordTextbox;
    @FindBy(id = "org.wikipedia:id/login_button")
    public WebElement loginButton;
    @FindBy(id = "org.wikipedia:id/snackbar_text")
    public WebElement wrongCredentialToastMessage;
    @FindBy(id = "org.wikipedia:id/explore_overflow_account_name")
    public WebElement displayUsername;
    @FindBy(xpath = "//android.widget.ImageButton[@content-desc=\"Navigate up\"]")
    public WebElement navigateButton;

    public Login_test_elements click_menu_overflow_button() {
        menuOverflowButton.click();
        return this;
    }

    public Login_test_elements click_logon_button() {
        logOnButton.click();
        return this;
    }

    public Login_test_elements enter_wrong_username_to_login() {
        usernameTextbox.click();
        usernameTextbox.sendKeys("rite2keshav");
        return this;
    }

    public Login_test_elements enter_wrong_password_to_login() {
        passwordTextbox.click();
        passwordTextbox.sendKeys("rite2keshav");
        return this;
    }

    public Login_test_elements click_login_button() throws InterruptedException {
        loginButton.click();
        Thread.sleep(5000);
        return this;
    }

    public Login_test_elements validate_wrong_credential_message() {
        Assert.assertTrue(wrongCredentialToastMessage.isDisplayed());
        Assert.assertTrue(wrongCredentialToastMessage.getText().contains(wrongCredentialMessage));
        return this;
    }

    public Login_test_elements enter_username_to_login() {
        usernameTextbox.clear();
        usernameTextbox.sendKeys("rite2keshav44");
        return this;
    }

    public Login_test_elements enter_password_to_login() {
        passwordTextbox.clear();
        passwordTextbox.sendKeys("rite2keshav55");
        return this;
    }

    public Login_test_elements click_navigate_button() throws InterruptedException {
        navigateButton.click();
        Thread.sleep(2000);
        return this;
    }

    public Login_test_elements validate_successful_login() {
        Assert.assertTrue(displayUsername.isDisplayed());
        Assert.assertTrue(displayUsername.getText().contains(displayUser));
        return this;
    }

    public Login_test_elements(WebDriver driver) {
        this.driver=driver;
    //  PageFactory.initElements(this.driver, this);
    }

}
</code>```

first class test class :

```<code>package wikipedia_login_page;

import org.openqa.selenium.support.PageFactory;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import wikipedia_app_setup.Wikipedia_app_launch;

public class Functional_login_tests extends Wikipedia_app_launch {
    public Login_test_elements loginTestElements;

    @BeforeClass
    public void initElementsBeforeClass() {
        loginTestElements = PageFactory.initElements(driver, Login_test_elements.class);
    }

    @Test(priority = 1, groups={"regression"}, description = "Login to wikipedia App with wrong credentials.\n"
            + "1. Click on menu button.\n"
            + "2. Click on logon button.\n"
            + "3. Enter wrong username.\n"
            + "4. Enter wrong password.\n"
            + "5. Click on login button.\n"
            + "6. Validate if app is showing wrong credential message.")
    public void validate_login_to_wikipedia_app_with_wrong_credential() throws InterruptedException {
        System.out.println("##### Current Function ####### " + new Functional_login_tests() {
        }.getClass().getEnclosingMethod().getName() + "()");
        loginTestElements
            .click_menu_overflow_button()
            .click_logon_button()
            .enter_wrong_username_to_login()
            .enter_wrong_password_to_login()
            .click_login_button()
            .validate_wrong_credential_message();
    }

    @Test(priority = 2, groups={"regression"}, description = "Login to wikipedia App.\n"
            + "1. Click on menu button.\n"
            + "2. Click on logon button.\n"
            + "3. Enter username.\n"
            + "4. Enter password.\n"
            + "5. Click on login button.\n"
            + "6. Validate if login is success.")
    public void validate_login_to_wikipedia_app() throws InterruptedException {
        System.out.println("##### Current Function ####### " + new Functional_login_tests() {
        }.getClass().getEnclosingMethod().getName() + "()");
        loginTestElements
            .enter_username_to_login()
            .enter_password_to_login()
            .click_login_button()
            .click_menu_overflow_button()
            .validate_successful_login();
    }
}
</code>```

Second class locators class :

```<code>package wikipedia_search_bookmark;

import java.util.List;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.FindBys;

import junit.framework.Assert;

public class Search_bookmark_test_elements {

    public WebDriver driver;

    public final String searchedTitle = "Java";
    public final String bookmarkName = "ProgLangArticles";
    public final String articleAddedMessage = "Added to";
    public final String articleRemovedMessage = "removed from list";

    // Form Elements
    @FindBy(id = "org.wikipedia:id/explore_overflow_account_name")
    public WebElement displayUsername;
    @FindBy(id = "org.wikipedia:id/search_container")
    public WebElement searchArticleBox;
    @FindBy(id = "org.wikipedia:id/search_src_text")
    public WebElement searchTextbox;
    @FindBys({ @FindBy(id = "org.wikipedia:id/page_list_item_container") })
    private List<WebElement> searchedItems;
    @FindBy(id = "org.wikipedia:id/view_page_title_text")
    public WebElement searchedItemTitle;
    @FindBy(xpath = "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.support.v4.widget.DrawerLayout/android.view.ViewGroup/android.view.ViewGroup/android.widget.HorizontalScrollView/android.widget.LinearLayout/android.support.v7.app.ActionBar.Tab[1]")
    public WebElement bookmarkButton;
    @FindBy(id = "org.wikipedia:id/onboarding_button")
    public WebElement gotItButton;
    @FindBy(id = "org.wikipedia:id/text_input")
    public WebElement bookmarkNameTextbox;
    @FindBy(id = "android:id/button1")
    public WebElement saveBookmarkButton;
    @FindBy(id = "org.wikipedia:id/snackbar_text")
    public WebElement addedToBookmarkListMessage;
    @FindBy(xpath = "/hierarchy/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.ListView/android.widget.LinearLayout[2]")
    public WebElement removeArticleFromListButton;
    @FindBy(xpath = "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.support.v4.widget.DrawerLayout/android.view.ViewGroup/android.view.ViewGroup/android.widget.FrameLayout[2]/android.widget.LinearLayout/android.widget.TextView")
    public WebElement removedFromBookmarkListMessage;

    public Search_bookmark_test_elements click_display_username() {
        displayUsername.click();
        return this;
    }

    public Search_bookmark_test_elements click_search_article_textbox() {
        searchArticleBox.click();
        return this;
    }

    public Search_bookmark_test_elements enter_article_to_search() throws InterruptedException {
        searchTextbox.sendKeys("java");
        Thread.sleep(5000);
        return this;
    }

    public Search_bookmark_test_elements select_searched_item() throws InterruptedException {
        searchedItems.get(1).click();
        Thread.sleep(5000);
        return this;
    }

    public Search_bookmark_test_elements validate_selected_item_title() {
        Assert.assertTrue(searchedItemTitle.isDisplayed());
        Assert.assertTrue(searchedItemTitle.getText().contains(searchedTitle));
        return this;
    }

    public Search_bookmark_test_elements click_bookmark_button() {
        bookmarkButton.click();
        return this;
    }

    public Search_bookmark_test_elements click_gotit_button() {
        gotItButton.click();
        return this;
    }

    public Search_bookmark_test_elements enter_bookmark_name() {
        bookmarkNameTextbox.clear();
        bookmarkNameTextbox.sendKeys(bookmarkName);
        return this;
    }

    public Search_bookmark_test_elements click_save_bookmark_button() {
        saveBookmarkButton.click();
        return this;
    }

    public Search_bookmark_test_elements validate_article_added_to_bookmark() {
        Assert.assertTrue(addedToBookmarkListMessage.isDisplayed());
        Assert.assertTrue(addedToBookmarkListMessage.getText().contains(articleAddedMessage));
        searchedItemTitle.click();
        return this;
    }

    public Search_bookmark_test_elements click_remove_article_from_list_button() {
        removeArticleFromListButton.click();
        return this;
    }

    public Search_bookmark_test_elements validate_article_removed_from_list() {
        Assert.assertTrue(removedFromBookmarkListMessage.isDisplayed());
        Assert.assertTrue(removedFromBookmarkListMessage.getText().contains(articleRemovedMessage));
        return this;
    }

    public Search_bookmark_test_elements(WebDriver driver) {
        this.driver=driver;
        //PageFactory.initElements(new AppiumFieldDecorator(driver), this);
    }
}
</code>```

Second class test class :

```<code>package wikipedia_search_bookmark;

import org.openqa.selenium.support.PageFactory;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import wikipedia_app_setup.Wikipedia_app_launch;

public class Functional_search_bookmark_tests extends Wikipedia_app_launch {

    public Search_bookmark_test_elements searchbookmarkTestElements;

    @BeforeClass
    public void initElementsBeforeClass() {
        searchbookmarkTestElements = PageFactory.initElements(driver, Search_bookmark_test_elements.class);
    }

    @Test(priority = 1, groups={"regression"}, description = "Validate search item and its title.\n"
            + "1. Search for an item.\n"
            + "2. Validate searched item title.")
    public void validate_search_article_and_title() throws InterruptedException {
        System.out.println("##### Current Function ####### " + new Functional_search_bookmark_tests() {
        }.getClass().getEnclosingMethod().getName() + "()");
        searchbookmarkTestElements
        //  .click_display_username()
            .click_search_article_textbox()
            .enter_article_to_search()
            .select_searched_item()
            .validate_selected_item_title();
    }

    @Test(priority = 2, groups={"regression"}, description = "Validate add bookmark.\n"
            + "1. Search for an item.\n"
            + "2. Add item to bookmark.")
    public void validate_search_article_add_bookmark() throws InterruptedException {
        System.out.println("##### Current Function ####### " + new Functional_search_bookmark_tests() {
        }.getClass().getEnclosingMethod().getName() + "()");
        searchbookmarkTestElements
            .click_bookmark_button()
            .click_gotit_button()
            .enter_bookmark_name()
            .click_save_bookmark_button()
            .validate_article_added_to_bookmark();
    }

    @Test(priority = 3, groups={"regression"}, description = "Validate remove article from bookmark.\n"
            + "1. Click on bookmark button.\n"
            + "2. Remove Item from bookmark.")
    public void validate_search_article_remove_bookmark() throws InterruptedException {
        System.out.println("##### Current Function ####### " + new Functional_search_bookmark_tests() {
        }.getClass().getEnclosingMethod().getName() + "()");
        searchbookmarkTestElements
            .click_bookmark_button()
            .click_remove_article_from_list_button()
            .validate_article_removed_from_list();
    }
}
</code>```

Testng.xml :

```<code><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">

    <test name="Functional_login_tests" preserve-order="true" parallel="none" verbose="2">
        <!-- <groups>
            <run>
                <include name="regression"
            </run>
        </groups> -->
        <classes>
            <class name="wikipedia_login_page.Functional_login_tests" />
        </classes>
    </test>

    <test name="Functional_search_bookmark_tests" preserve-order="true" parallel="none" verbose="2">
        <!-- <groups>
            <run>
                <include name="regression" />
            </run>
        </groups> -->
        <classes>
            <class
                name="wikipedia_search_bookmark.Functional_search_bookmark_tests" />
        </classes>
    </test>

    <!-- <test name="Functional_rotate_app_tests" preserve-order="true" parallel="none"
        verbose="2"> <groups> <run> <include name="preProdSanity" /> <include name="prodSanity"
        /> <include name="regression" /> </run> </groups> <classes> <class name="wikipedia_rotate_app.Functional_rotate_app_tests"
        /> </classes> </test> -->
</suite> <!-- Suite -->

</code>```

答:
You need to change

```<code>public WebDriver driver;
</code>```

To

```<code>public static WebDriver driver;
</code>```

Explain: So in the above setup both TestNG classes have their own instance of Setup class. TestNG will club @BeforeSuite methods from both instances of Setup class as only one while running as a suite. So when the @BeforeSuite method runs it initializes the common variable driver for the first TestNG class which was consumed by @Test methods of the First TestNG class. When the execution of the Second TestNG class begins, @BeforeSuite will not be executed again which results in the non-initialization of the very own copy of variable driver in SecondTestNGClass and it remains NULL.

Same issue was resolved for me from here http://makeseleniumeasy..., visit that website for the full explanation with example

Body:
Appium application is giving null pointer exception if using two or more classes in testng.xml
Attached are the codes below. If I use any one of the class in testng.xml file, it works fine. But if I define both the classes in testng.xml file, it gives null pointer exception. Please help...
Application driver class :

package wikipedia_app_setup;

import java.net.URL;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;

public class Wikipedia_app_launch {
    //public static AppiumDriver<MobileElement> driver;
    public WebDriver driver;

    @BeforeSuite
    public WebDriver openWikipedia() throws Exception
    {
        DesiredCapabilities dc=new DesiredCapabilities();
        dc.setCapability("deviceName", "Moto g5 plus");
        dc.setCapability("udid","ZY223XXDVV");
        dc.setCapability("platformName","Android");
        dc.setCapability("platformVersion","8.1.0");
        dc.setCapability("app","C:\\Users\\Keshavgoyal\\Downloads\\org.wikipedia.apk");
/*      dc.setCapability("appPackage","com.google.android.calculator");
        dc.setCapability("appActivity","com.android.calculator2.Calculator");*/
        URL url=new URL("http://127.0.0.1:4723/wd/hub");
        driver=new AppiumDriver<MobileElement>(url,dc);
        System.out.println("Application Started");
        Thread.sleep(10000);

    return driver;
}

    @AfterSuite
    public void closeWikipedia() throws Exception
    {
        driver.quit();
}
}

First class locators class :

package wikipedia_login_page;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

import junit.framework.Assert;

public class Login_test_elements  {

    //public AppiumDriver<WebElement> driver;

    public WebDriver driver;
    public final String wrongCredentialMessage = "Incorrect username or password entered";

    // Form Elements
    @FindBy(id ="org.wikipedia:id/menu_overflow_button")
    public WebElement menuOverflowButton;
    @FindBy(id = "org.wikipedia:id/explore_overflow_account_container")
    public WebElement logOnButton;
    @FindBy(id = "org.wikipedia:id/login_username_text")
    public WebElement usernameTextbox;
    @FindBy(xpath = "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[2]/android.widget.FrameLayout/android.widget.ScrollView/android.widget.LinearLayout/TextInputLayout[2]/android.widget.FrameLayout/android.widget.EditText")
    public WebElement passwordTextbox;
    @FindBy(id = "org.wikipedia:id/login_button")
    public WebElement loginButton;
    @FindBy(id = "org.wikipedia:id/snackbar_text")
    public WebElement wrongCredentialToastMessage;
    @FindBy(id = "org.wikipedia:id/explore_overflow_account_name")
    public WebElement displayUsername;
    @FindBy(xpath = "//android.widget.ImageButton[@content-desc=\"Navigate up\"]")
    public WebElement navigateButton;

    public Login_test_elements click_menu_overflow_button() {
        menuOverflowButton.click();
        return this;
    }

    public Login_test_elements click_logon_button() {
        logOnButton.click();
        return this;
    }

    public Login_test_elements enter_wrong_username_to_login() {
        usernameTextbox.click();
        usernameTextbox.sendKeys("rite2keshav");
        return this;
    }

    public Login_test_elements enter_wrong_password_to_login() {
        passwordTextbox.click();
        passwordTextbox.sendKeys("rite2keshav");
        return this;
    }

    public Login_test_elements click_login_button() throws InterruptedException {
        loginButton.click();
        Thread.sleep(5000);
        return this;
    }

    public Login_test_elements validate_wrong_credential_message() {
        Assert.assertTrue(wrongCredentialToastMessage.isDisplayed());
        Assert.assertTrue(wrongCredentialToastMessage.getText().contains(wrongCredentialMessage));
        return this;
    }

    public Login_test_elements enter_username_to_login() {
        usernameTextbox.clear();
        usernameTextbox.sendKeys("rite2keshav44");
        return this;
    }

    public Login_test_elements enter_password_to_login() {
        passwordTextbox.clear();
        passwordTextbox.sendKeys("rite2keshav55");
        return this;
    }

    public Login_test_elements click_navigate_button() throws InterruptedException {
        navigateButton.click();
        Thread.sleep(2000);
        return this;
    }

    public Login_test_elements validate_successful_login() {
        Assert.assertTrue(displayUsername.isDisplayed());
        Assert.assertTrue(displayUsername.getText().contains(displayUser));
        return this;
    }

    public Login_test_elements(WebDriver driver) {
        this.driver=driver;
    //  PageFactory.initElements(this.driver, this);
    }

}

first class test class :

package wikipedia_login_page;

import org.openqa.selenium.support.PageFactory;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import wikipedia_app_setup.Wikipedia_app_launch;

public class Functional_login_tests extends Wikipedia_app_launch {
    public Login_test_elements loginTestElements;

    @BeforeClass
    public void initElementsBeforeClass() {
        loginTestElements = PageFactory.initElements(driver, Login_test_elements.class);
    }

    @Test(priority = 1, groups={"regression"}, description = "Login to wikipedia App with wrong credentials.\n"
            + "1. Click on menu button.\n"
            + "2. Click on logon button.\n"
            + "3. Enter wrong username.\n"
            + "4. Enter wrong password.\n"
            + "5. Click on login button.\n"
            + "6. Validate if app is showing wrong credential message.")
    public void validate_login_to_wikipedia_app_with_wrong_credential() throws InterruptedException {
        System.out.println("##### Current Function ####### " + new Functional_login_tests() {
        }.getClass().getEnclosingMethod().getName() + "()");
        loginTestElements
            .click_menu_overflow_button()
            .click_logon_button()
            .enter_wrong_username_to_login()
            .enter_wrong_password_to_login()
            .click_login_button()
            .validate_wrong_credential_message();
    }

    @Test(priority = 2, groups={"regression"}, description = "Login to wikipedia App.\n"
            + "1. Click on menu button.\n"
            + "2. Click on logon button.\n"
            + "3. Enter username.\n"
            + "4. Enter password.\n"
            + "5. Click on login button.\n"
            + "6. Validate if login is success.")
    public void validate_login_to_wikipedia_app() throws InterruptedException {
        System.out.println("##### Current Function ####### " + new Functional_login_tests() {
        }.getClass().getEnclosingMethod().getName() + "()");
        loginTestElements
            .enter_username_to_login()
            .enter_password_to_login()
            .click_login_button()
            .click_menu_overflow_button()
            .validate_successful_login();
    }
}

Second class locators class :

package wikipedia_search_bookmark;

import java.util.List;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.FindBys;

import junit.framework.Assert;

public class Search_bookmark_test_elements {

    public WebDriver driver;

    public final String searchedTitle = "Java";
    public final String bookmarkName = "ProgLangArticles";
    public final String articleAddedMessage = "Added to";
    public final String articleRemovedMessage = "removed from list";

    // Form Elements
    @FindBy(id = "org.wikipedia:id/explore_overflow_account_name")
    public WebElement displayUsername;
    @FindBy(id = "org.wikipedia:id/search_container")
    public WebElement searchArticleBox;
    @FindBy(id = "org.wikipedia:id/search_src_text")
    public WebElement searchTextbox;
    @FindBys({ @FindBy(id = "org.wikipedia:id/page_list_item_container") })
    private List<WebElement> searchedItems;
    @FindBy(id = "org.wikipedia:id/view_page_title_text")
    public WebElement searchedItemTitle;
    @FindBy(xpath = "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.support.v4.widget.DrawerLayout/android.view.ViewGroup/android.view.ViewGroup/android.widget.HorizontalScrollView/android.widget.LinearLayout/android.support.v7.app.ActionBar.Tab[1]")
    public WebElement bookmarkButton;
    @FindBy(id = "org.wikipedia:id/onboarding_button")
    public WebElement gotItButton;
    @FindBy(id = "org.wikipedia:id/text_input")
    public WebElement bookmarkNameTextbox;
    @FindBy(id = "android:id/button1")
    public WebElement saveBookmarkButton;
    @FindBy(id = "org.wikipedia:id/snackbar_text")
    public WebElement addedToBookmarkListMessage;
    @FindBy(xpath = "/hierarchy/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.ListView/android.widget.LinearLayout[2]")
    public WebElement removeArticleFromListButton;
    @FindBy(xpath = "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.support.v4.widget.DrawerLayout/android.view.ViewGroup/android.view.ViewGroup/android.widget.FrameLayout[2]/android.widget.LinearLayout/android.widget.TextView")
    public WebElement removedFromBookmarkListMessage;

    public Search_bookmark_test_elements click_display_username() {
        displayUsername.click();
        return this;
    }

    public Search_bookmark_test_elements click_search_article_textbox() {
        searchArticleBox.click();
        return this;
    }

    public Search_bookmark_test_elements enter_article_to_search() throws InterruptedException {
        searchTextbox.sendKeys("java");
        Thread.sleep(5000);
        return this;
    }

    public Search_bookmark_test_elements select_searched_item() throws InterruptedException {
        searchedItems.get(1).click();
        Thread.sleep(5000);
        return this;
    }

    public Search_bookmark_test_elements validate_selected_item_title() {
        Assert.assertTrue(searchedItemTitle.isDisplayed());
        Assert.assertTrue(searchedItemTitle.getText().contains(searchedTitle));
        return this;
    }

    public Search_bookmark_test_elements click_bookmark_button() {
        bookmarkButton.click();
        return this;
    }

    public Search_bookmark_test_elements click_gotit_button() {
        gotItButton.click();
        return this;
    }

    public Search_bookmark_test_elements enter_bookmark_name() {
        bookmarkNameTextbox.clear();
        bookmarkNameTextbox.sendKeys(bookmarkName);
        return this;
    }

    public Search_bookmark_test_elements click_save_bookmark_button() {
        saveBookmarkButton.click();
        return this;
    }

    public Search_bookmark_test_elements validate_article_added_to_bookmark() {
        Assert.assertTrue(addedToBookmarkListMessage.isDisplayed());
        Assert.assertTrue(addedToBookmarkListMessage.getText().contains(articleAddedMessage));
        searchedItemTitle.click();
        return this;
    }

    public Search_bookmark_test_elements click_remove_article_from_list_button() {
        removeArticleFromListButton.click();
        return this;
    }

    public Search_bookmark_test_elements validate_article_removed_from_list() {
        Assert.assertTrue(removedFromBookmarkListMessage.isDisplayed());
        Assert.assertTrue(removedFromBookmarkListMessage.getText().contains(articleRemovedMessage));
        return this;
    }

    public Search_bookmark_test_elements(WebDriver driver) {
        this.driver=driver;
        //PageFactory.initElements(new AppiumFieldDecorator(driver), this);
    }
}

Second class test class :

package wikipedia_search_bookmark;

import org.openqa.selenium.support.PageFactory;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import wikipedia_app_setup.Wikipedia_app_launch;

public class Functional_search_bookmark_tests extends Wikipedia_app_launch {

    public Search_bookmark_test_elements searchbookmarkTestElements;

    @BeforeClass
    public void initElementsBeforeClass() {
        searchbookmarkTestElements = PageFactory.initElements(driver, Search_bookmark_test_elements.class);
    }

    @Test(priority = 1, groups={"regression"}, description = "Validate search item and its title.\n"
            + "1. Search for an item.\n"
            + "2. Validate searched item title.")
    public void validate_search_article_and_title() throws InterruptedException {
        System.out.println("##### Current Function ####### " + new Functional_search_bookmark_tests() {
        }.getClass().getEnclosingMethod().getName() + "()");
        searchbookmarkTestElements
        //  .click_display_username()
            .click_search_article_textbox()
            .enter_article_to_search()
            .select_searched_item()
            .validate_selected_item_title();
    }

    @Test(priority = 2, groups={"regression"}, description = "Validate add bookmark.\n"
            + "1. Search for an item.\n"
            + "2. Add item to bookmark.")
    public void validate_search_article_add_bookmark() throws InterruptedException {
        System.out.println("##### Current Function ####### " + new Functional_search_bookmark_tests() {
        }.getClass().getEnclosingMethod().getName() + "()");
        searchbookmarkTestElements
            .click_bookmark_button()
            .click_gotit_button()
            .enter_bookmark_name()
            .click_save_bookmark_button()
            .validate_article_added_to_bookmark();
    }

    @Test(priority = 3, groups={"regression"}, description = "Validate remove article from bookmark.\n"
            + "1. Click on bookmark button.\n"
            + "2. Remove Item from bookmark.")
    public void validate_search_article_remove_bookmark() throws InterruptedException {
        System.out.println("##### Current Function ####### " + new Functional_search_bookmark_tests() {
        }.getClass().getEnclosingMethod().getName() + "()");
        searchbookmarkTestElements
            .click_bookmark_button()
            .click_remove_article_from_list_button()
            .validate_article_removed_from_list();
    }
}

Testng.xml :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">

    <test name="Functional_login_tests" preserve-order="true" parallel="none" verbose="2">

        <classes>
            <class name="wikipedia_login_page.Functional_login_tests" />
        </classes>
    </test>

    <test name="Functional_search_bookmark_tests" preserve-order="true" parallel="none" verbose="2">

        <classes>
            <class
                name="wikipedia_search_bookmark.Functional_search_bookmark_tests" />
        </classes>
    </test>

</suite>

Body:
You need to change

public WebDriver driver;

To

public static WebDriver driver;

Explain: So in the above setup both TestNG classes have their own instance of Setup class. TestNG will club @BeforeSuite methods from both instances of Setup class as only one while running as a suite. So when the @BeforeSuite method runs it initializes the common variable driver for the first TestNG class which was consumed by @Test methods of the First TestNG class. When the execution of the Second TestNG class begins, @BeforeSuite will not be executed again which results in the non-initialization of the very own copy of variable driver in SecondTestNGClass and it remains NULL.

Same issue was resolved for me from here http://makeseleniumeasy..., visit that website for the full explanation with example


来源: stackexchange

问:
Efficient overflow-immune arithmetic mean in C/C++
The arithmetic mean of two unsigned integers is defined as:

```<code>mean = (a+b)/2
</code>```

Directly implementing this in C/C++ may overflow and produce a wrong result. A correct implementation would avoid this. One way of coding it could be:

```<code>mean = a/2 + b/2 + (a%2 + b%2)/2
</code>```

But this produces rather a lot of code with typical compilers. In assembler, this usually can be done much more efficiently. For example, the x86 can do this in the following way (assembler pseudo code, I hope you get the point):

```<code>ADD a,b   ; addition, leaving the overflow condition in the carry bit
RCR a,1   ; rotate right through carry, effectively a division by 2
</code>```

After those two instructions, the result is in a, and the remainder of the division is in the carry bit. If correct rounding is desired, a third ADC instruction would have to add the carry into the result.

Note that the RCR instruction is used, which rotates a register through the carry. In our case, it is a rotate by one position, so that the previous carry becomes the most significant bit in the register, and the new carry holds the previous LSB from the register. It seems that MSVC doesn't even offer an intrinsic for this instruction.

Is there a known C/C++ pattern that can be expected to be recognized by an optimizing compiler so that it produces such efficient code? Or, more generally, is there a rational way how to program in C/C++ source level so that the carry bit is being used by the compiler to optimize the generated code?

EDIT:

A 1-hour lecture about std::midpoint: https://www.youtube.com/watch?v=sBtAGxBh-XI

Wow!

EDIT2: Great discussion on Microsoft blog

答:
The following method avoids overflow and should result in fairly efficient assembly (example) without depending on non-standard features:</p>
```<code>    mean = (a&b) + (a^b)/2;
</code>```

ContentLicense: CC BY-SA 4.0

Body:
The arithmetic mean of two unsigned integers is defined as:

mean = (a+b)/2

Directly implementing this in C/C++ may overflow and produce a wrong result. A correct implementation would avoid this. One way of coding it could be:

mean = a/2 + b/2 + (a%2 + b%2)/2

But this produces rather a lot of code with typical compilers. In assembler, this usually can be done much more efficiently. For example, the x86 can do this in the following way (assembler pseudo code, I hope you get the point):

ADD a,b   ; addition, leaving the overflow condition in the carry bit
RCR a,1   ; rotate right through carry, effectively a division by 2

After those two instructions, the result is in a, and the remainder of the division is in the carry bit. If correct rounding is desired, a third ADC instruction would have to add the carry into the result.

Note that the RCR instruction is used, which rotates a register through the carry. In our case, it is a rotate by one position, so that the previous carry becomes the most significant bit in the register, and the new carry holds the previous LSB from the register. It seems that MSVC doesn't even offer an intrinsic for this instruction.

Is there a known C/C++ pattern that can be expected to be recognized by an optimizing compiler so that it produces such efficient code? Or, more generally, is there a rational way how to program in C/C++ source level so that the carry bit is being used by the compiler to optimize the generated code?

EDIT:

A 1-hour lecture about std::midpoint: https://www.youtube.com/watch?v=sBtAGxBh-XI

Wow!

EDIT2: Great discussion on Microsoft blog

Body:
The following method avoids overflow and should result in fairly efficient assembly (example) without depending on non-standard features:

    mean = (a&b) + (a^b)/2;


问:
Sublime Text 4 node_modules go to definition, typescript/node
Is there a way to configure Sublime Text 4 so that the Go To Definition context menu item works for imports/requires?

I'm not having any issues with the go to definition for things defined myself, but when trying to view the imported module type definitions. Looking for behavior similar to VSCode's with this, or at least alternative but similar end result behavior.

This is on a clean install of ST4, node_modules is not in any exclude path in the settings.

答: Had to set the "index_exclude_gitignore": false to get ST4 to index the node_modules folder to get this behavior working.</p>


问:
Comparing two arrays in C ignoring the order of the elements inside each array
I want to compare two arrays in C, ignoring the order of the elements inside each array, I had two ideas to solve this problem.
Well, they're the same, to be honest. The first idea is to make a variable and increment it with 1 if we find our element inside the second table (please see the code below).
But this one doesn't work if we give it as an example {3, 2, 2, 1} {1, 2, 3, 4}.
the second idea (which I obviously couldn't code) is: setting a variable c=0 for example, after the first loop:

```<code>for (i = 0; i < n; i++) {
    c = 0;
    for (...
}
</code>```

this c will count the number of fails

```<code>if (T1[i] != T2[j]) {
    c += 1
}
</code>```

Then before exiting the j loop, we check if c==n where n is the length of the table. Meaning we have n fails.
after that, unsetting cat the beginning of the i loop

this is my code:

```<code>#include <stdio.h>

int main() {
    int n, i, j, c = 0;
    printf("give the size of the first array: \n");
    scanf("%d", &n);
    int T1[n];
    int T2[n];
    // remplissage de T1
    for (i = 0; i < n; i++) {
        printf("give the value of %d case, table1: ", i + 1);
        scanf("%d", &T1[i]);
    }
    // remplissage de T2
    for (i = 0; i < n; i++) {
        printf("give the value of %d case, table2: ", i + 1);
        scanf("%d", &T2[i]);
    }
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            if (T1[i] == T2[j]) {
                c += 1;
                break;
            }
        }
    }
    if (c == n) {
        printf("True");
    } else {
        printf("False");
    }
}
</code>```

答:
Your approach fails if there are duplicates in the first array: { 0, 0 } will compare equal to { 0, 1 }. If you were to compare T1 and T2 both ways, you would still have this counter example: { 0, 0, 1 } and { 0, 1, 1 }.

You can work around this problem by counting the number of occurrences in both arrays of each element in one of the arrays: the arrays contain the same numbers if all counts match:

```<code>#include <stdio.h>

int count(int val, const int *T, int n) {
    int c = 0;
    for (int i = 0; i < n; i++)
        c += (T[i] == val);
    return c;
}

int main() {
    int n, i;
    printf("give the size of the first array: \n");
    if (scanf("%d", &n) != 1)
        return 1;
    int T1[n];
    int T2[n];
    // remplissage de T1
    for (i = 0; i < n; i++) {
        printf("give the value of %d case, table1: ", i + 1);
        if (scanf("%d", &T1[i]) != 1)
            return 1;
    }
    // remplissage de T2
    for (i = 0; i < n; i++) {
        printf("give the value of %d case, table2: ", i + 1);
        if (scanf("%d", &T2[i]) != 1)
            return 1;
    }
    for (i = 0; i < n; i++) {
        if (count(T1[i], T1, n) != count(T1[i], T2, n))
            break;
    }
    if (i == n) {
        printf("True\n");
    } else {
        printf("False\n");
    }
    return 0;
}
</code>```

The above code has a time complexity of O(n2) because of the nested loops. You pay get better performance for large n by sorting both arrays and comparing them sequentially (complexity O(n.log(n)).)

Body:
I want to compare two arrays in C, ignoring the order of the elements inside each array, I had two ideas to solve this problem.
Well, they're the same, to be honest. The first idea is to make a variable and increment it with 1 if we find our element inside the second table (please see the code below).
But this one doesn't work if we give it as an example {3, 2, 2, 1} {1, 2, 3, 4}.
the second idea (which I obviously couldn't code) is: setting a variable c=0 for example, after the first loop:

for (i = 0; i < n; i++) {
    c = 0;
    for (...
}

this c will count the number of fails

if (T1[i] != T2[j]) {
    c += 1
}

Then before exiting the j loop, we check if c==n where n is the length of the table. Meaning we have n fails.
after that, unsetting cat the beginning of the i loop

this is my code:

#include <stdio.h>

int main() {
    int n, i, j, c = 0;
    printf("give the size of the first array: \n");
    scanf("%d", &n);
    int T1[n];
    int T2[n];
    // remplissage de T1
    for (i = 0; i < n; i++) {
        printf("give the value of %d case, table1: ", i + 1);
        scanf("%d", &T1[i]);
    }
    // remplissage de T2
    for (i = 0; i < n; i++) {
        printf("give the value of %d case, table2: ", i + 1);
        scanf("%d", &T2[i]);
    }
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            if (T1[i] == T2[j]) {
                c += 1;
                break;
            }
        }
    }
    if (c == n) {
        printf("True");
    } else {
        printf("False");
    }
}

Body:
Your approach fails if there are duplicates in the first array: { 0, 0 } will compare equal to { 0, 1 }. If you were to compare T1 and T2 both ways, you would still have this counter example: { 0, 0, 1 } and { 0, 1, 1 }.

You can work around this problem by counting the number of occurrences in both arrays of each element in one of the arrays: the arrays contain the same numbers if all counts match:

#include <stdio.h>

int count(int val, const int *T, int n) {
    int c = 0;
    for (int i = 0; i < n; i++)
        c += (T[i] == val);
    return c;
}

int main() {
    int n, i;
    printf("give the size of the first array: \n");
    if (scanf("%d", &n) != 1)
        return 1;
    int T1[n];
    int T2[n];
    // remplissage de T1
    for (i = 0; i < n; i++) {
        printf("give the value of %d case, table1: ", i + 1);
        if (scanf("%d", &T1[i]) != 1)
            return 1;
    }
    // remplissage de T2
    for (i = 0; i < n; i++) {
        printf("give the value of %d case, table2: ", i + 1);
        if (scanf("%d", &T2[i]) != 1)
            return 1;
    }
    for (i = 0; i < n; i++) {
        if (count(T1[i], T1, n) != count(T1[i], T2, n))
            break;
    }
    if (i == n) {
        printf("True\n");
    } else {
        printf("False\n");
    }
    return 0;
}

The above code has a time complexity of O(n2) because of the nested loops. You pay get better performance for large n by sorting both arrays and comparing them sequentially (complexity O(n.log(n)).)


问:
Is it possible to use WebRTC to streaming video from Server to Client?
In WebRTC, I always see the implementation about peer-to-peer and how to get video streaming from one client to another client. How about server-to-client?

Is it possible for WebRTC to streaming video file from server-to-client?
(I am thinking about using WebRTC Native C++ API to create my own server application to connect to the current implementation on chrome or firefox browser client application.)

OK, if it is possible, will it be faster than many current video streaming services?

答:
Sure it's possible, it allows covert live streaming to WebRTC, for example:

```<code>OBS/FFmpeg ---RTMP---> Server ---WebRTC--> Chrome/Client
</code>```

For this scenario, it allows the ultra low latency live streaming, about 600~800ms, to play the  live streaming by WebRTC. Please take a look at this demo.

ContentLicense: CC BY-SA 3.0

Body:
Sure it's possible, it allows covert live streaming to WebRTC, for example:

OBS/FFmpeg ---RTMP---> Server ---WebRTC--> Chrome/Client

For this scenario, it allows the ultra low latency live streaming, about 600~800ms, to play the  live streaming by WebRTC. Please take a look at this demo.


问:
How to plot with ggplot grouped data in two levels?
Here is my data set:

```<code>SP <- c("DC","DC","DP","DP","DC")
ES <- c("CA","CA","CA","CA","CK")
W <- c("B","A","B","A","B")
P <- c(0.5,0.77,0,0.43,.38)
df <- data.frame(SP, ES, W, P)
</code>```

I would like to plot this like in the picture that I made in excel. It is important that the data are grouped and have the space between each of them.

Please find below my excel barplot:

答:
Using adapted data here is a replica of the excel version.
This method creates a dummy continuous variable: brks to set out the breaks for the columns (there may be a smarter way to generate this sequence by a formula, but as there are so few points I've done this manually). The x axis labels are created by combining the three variables, ordering and setting as factors to ensure they plot in the required order.

dat <- data.frame(SP = rep(rep(c("DC", "DP"), each = 2), 3),
                  ES = rep(c("CA", "CK", "HD"), each = 4),
                  W = rep(c("B", "A"), 6),
                  P = c("50%", "77%", "5%", "43%", "38%", "68%", "3%", "26%", "13%", "5%", "2%", "4%"))

library(dplyr)
library(stringr)
library(forcats)
library(ggplot2)

dat1 <-
  dat %>%
  arrange(ES, SP, desc(W)) %>%
  mutate(P = as.numeric(str_extract(P, "\\d+"))/100,
         x_lab = fct_inorder(paste(W, ES, SP, sep = "\n\n")),
         brks = c(1, 2, 4, 5, 9, 10, 12, 13, 17, 18, 20, 21))

ggplot(dat1, aes(brks, P))+
  geom_col(fill = "deepskyblue4", width = 0.95)+
  geom_text(aes(label = scales::percent(P, accuracy = 1)),
            vjust = 1.5,
            colour = "white",
            size = 3)+
  scale_x_continuous(breaks = dat1$brks,
                     labels = dat1$x_lab)+
  scale_y_continuous(expand = expansion(mult = c(0, 0.05)))+
  labs(x = NULL,
       y = NULL)+
  theme_bw()+
  theme(axis.ticks = element_blank(),
        axis.text.y = element_blank(),
        panel.border = element_blank(),
        panel.grid = element_blank())
```
<p><img src="https://i.imgur.com/jGxd5Sg.png" alt="" /></p>
<p><sup>Created on 2022-02-10 by the reprex package (v2.0.1)</sup></p>
<p>Using your original data, here is one approach using ggplot's <code>facet_wrap</code>.</p>
<p>Note: shadows are not good practice for graphs.</p>
<pre class="lang-r prettyprint-override"><code>dat <- data.frame(SP = rep(rep(c("DC", "DP"), each = 2), 3),
                  ES = rep(c("CA", "CK", "HD"), each = 4),
                  W = rep(c("B", "A"), 6),
                  P = c("50%", "77%", "0%", "43%", "38%", "68%", "0%", "26%", "13%", "5%", "0%", "4%"))

library(dplyr)
library(stringr)
library(ggplot2)

dat %>%
  mutate(P = as.numeric(str_extract(P, "\\d+"))/100) %>%
  ggplot(aes(SP, P, fill = W)) +
  geom_col(position = position_dodge2(width = 0.8, reverse = TRUE))+
  facet_wrap(~ES, nrow = 1)+
  geom_text(aes(label = scales::percent(P, accuracy = 1)),
            position = position_dodge2(width = 0.8, reverse = TRUE),
            vjust = 1.5,
            colour = "white",
            size = 3)+
  labs(x = NULL,
       y = NULL)+
  theme_bw()+
  theme(legend.position = "bottom",
        axis.ticks = element_blank(),
        axis.text.y = element_blank(),
        panel.border = element_blank(),
        panel.spacing = unit(30, "mm"))
</code>```

Created on 2022-02-07 by the reprex package (v2.0.1)

Body:
Here is my data set:

SP <- c("DC","DC","DP","DP","DC")
ES <- c("CA","CA","CA","CA","CK")
W <- c("B","A","B","A","B")
P <- c(0.5,0.77,0,0.43,.38)
df <- data.frame(SP, ES, W, P)

I would like to plot this like in the picture that I made in excel. It is important that the data are grouped and have the space between each of them.

Please find below my excel barplot:

Body:
Using adapted data here is a replica of the excel version.
This method creates a dummy continuous variable: brks to set out the breaks for the columns (there may be a smarter way to generate this sequence by a formula, but as there are so few points I've done this manually). The x axis labels are created by combining the three variables, ordering and setting as factors to ensure they plot in the required order.

dat <- data.frame(SP = rep(rep(c("DC", "DP"), each = 2), 3),
                  ES = rep(c("CA", "CK", "HD"), each = 4),
                  W = rep(c("B", "A"), 6),
                  P = c("50%", "77%", "5%", "43%", "38%", "68%", "3%", "26%", "13%", "5%", "2%", "4%"))

library(dplyr)
library(stringr)
library(forcats)
library(ggplot2)

dat1 <-
  dat %>%
  arrange(ES, SP, desc(W)) %>%
  mutate(P = as.numeric(str_extract(P, "\\d+"))/100,
         x_lab = fct_inorder(paste(W, ES, SP, sep = "\n\n")),
         brks = c(1, 2, 4, 5, 9, 10, 12, 13, 17, 18, 20, 21))

ggplot(dat1, aes(brks, P))+
  geom_col(fill = "deepskyblue4", width = 0.95)+
  geom_text(aes(label = scales::percent(P, accuracy = 1)),
            vjust = 1.5,
            colour = "white",
            size = 3)+
  scale_x_continuous(breaks = dat1$brks,
                     labels = dat1$x_lab)+
  scale_y_continuous(expand = expansion(mult = c(0, 0.05)))+
  labs(x = NULL,
       y = NULL)+
  theme_bw()+
  theme(axis.ticks = element_blank(),
        axis.text.y = element_blank(),
        panel.border = element_blank(),
        panel.grid = element_blank())

Created on 2022-02-10 by the reprex package (v2.0.1)

Using your original data, here is one approach using ggplot's facet_wrap.

Note: shadows are not good practice for graphs.

dat <- data.frame(SP = rep(rep(c("DC", "DP"), each = 2), 3),
                  ES = rep(c("CA", "CK", "HD"), each = 4),
                  W = rep(c("B", "A"), 6),
                  P = c("50%", "77%", "0%", "43%", "38%", "68%", "0%", "26%", "13%", "5%", "0%", "4%"))

library(dplyr)
library(stringr)
library(ggplot2)

dat %>%
  mutate(P = as.numeric(str_extract(P, "\\d+"))/100) %>%
  ggplot(aes(SP, P, fill = W)) +
  geom_col(position = position_dodge2(width = 0.8, reverse = TRUE))+
  facet_wrap(~ES, nrow = 1)+
  geom_text(aes(label = scales::percent(P, accuracy = 1)),
            position = position_dodge2(width = 0.8, reverse = TRUE),
            vjust = 1.5,
            colour = "white",
            size = 3)+
  labs(x = NULL,
       y = NULL)+
  theme_bw()+
  theme(legend.position = "bottom",
        axis.ticks = element_blank(),
        axis.text.y = element_blank(),
        panel.border = element_blank(),
        panel.spacing = unit(30, "mm"))

Created on 2022-02-07 by the reprex package (v2.0.1)


问:
Micronaut autowired equivalent with no constructor
I'm beginer in micronaut and I'm confused about how to inject dependencies in some cases.

I need to user a service into a json deserializer:

```<code>public class DecryptSerializer extends JsonDeserializer<String> {

private MyService myService ;

@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
    try {
        return myService.decrypt(p.getValueAsString());
    } catch (GeneralSecurityException e) {
        throw new IOException(e);
    }
}
</code>```

In spring I use to do it like this:

```<code>@Component
public class DecryptSerializer extends JsonDeserializer<String> {
private static MyService myService;

@Autowired
public void setCryptoService(MyService myService){
    DecryptSerializer.myService= myService;
}

@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
    try {
        return myService.decrypt(p.getValueAsString());
    } catch (GeneralSecurityException e) {
        throw new IOException(e);
    }
}
}
</code>```

Who can I do it in micronaut?

答:
Micronaut autowired equivalent with no constructor

In Micronaut you can use @jakarta.inject.Inject on a property or a setter method.  Instead of this:

```<code>@Autowired
public void setCryptoService(MyService myService){
    DecryptSerializer.myService= myService;
}
</code>```

You could have this:

```<code>@Inject
public void setCryptoService(MyService myService){
    // initializing a static property like this is a bad idea,
    // but unrelated to the question.
    DecryptSerializer.myService= myService;
}
</code>```

Body:
I'm beginer in micronaut and I'm confused about how to inject dependencies in some cases.

I need to user a service into a json deserializer:

public class DecryptSerializer extends JsonDeserializer<String> {

private MyService myService ;

@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
    try {
        return myService.decrypt(p.getValueAsString());
    } catch (GeneralSecurityException e) {
        throw new IOException(e);
    }
}

In spring I use to do it like this:

@Component
public class DecryptSerializer extends JsonDeserializer<String> {
private static MyService myService;

@Autowired
public void setCryptoService(MyService myService){
    DecryptSerializer.myService= myService;
}

@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
    try {
        return myService.decrypt(p.getValueAsString());
    } catch (GeneralSecurityException e) {
        throw new IOException(e);
    }
}
}

Who can I do it in micronaut?

Body:
Micronaut autowired equivalent with no constructor

In Micronaut you can use @jakarta.inject.Inject on a property or a setter method.  Instead of this:

@Autowired
public void setCryptoService(MyService myService){
    DecryptSerializer.myService= myService;
}

You could have this:

@Inject
public void setCryptoService(MyService myService){
    // initializing a static property like this is a bad idea,
    // but unrelated to the question.
    DecryptSerializer.myService= myService;
}


问:
R plotly: using scaleanchor and constraintoward leaves white space between plotted data and title
I created a kind of interactive calendar heatmap using the following code. It is quite long but should be reproducible.

```<code>library(plotly)
library(data.table)
library(tidyr)
library(htmlwidgets)
library(widgetframe)

df <- data.frame(dom = sequence(31,1,1),
             Januar= sample(50:500, 31),
             Februar = sample(50:500, 31),
             März =sample(50:500, 31),
             April = sample(50:500, 31),
             Mai = sample(50:500, 31))

df <- as.data.table(df)
df<- melt(df, id.vars= "dom",variable.name="month",value.name="value", na.rm=T)
df<- as.data.frame(df)
df <- df %>% mutate(month= factor(month,levels=as.character(c("Januar","Februar","März","April","Mai")),labels=c("Jan","Feb","Mär","Apr","Mai"),ordered=TRUE))
df$dommapped <- ordered(df$dom, levels = 31:1)
df <- df%>% mutate(group=ceiling(value/(max(value)/5)))
df$group_1<- ifelse(df$group==1,df$group,NA)
df$group_2<- ifelse(df$group==2,df$group,NA)
df$group_3<- ifelse(df$group==3,df$group,NA)
df$group_4<- ifelse(df$group==4,df$group,NA)
df$group_5<- ifelse(df$group==5,df$group,NA)

colorScale1 <- data.frame(z=c(0,1),col=c("#FFE27a","#FFE27a"))
colorScale1$col <- as.character(colorScale1$col)
colorScale2 <- data.frame(z=c(0,1),col=c("#FFCD0e","#FFCD0e"))
colorScale2$col <- as.character(colorScale2$col)
colorScale3 <- data.frame(z=c(0,1),col=c("#A1C863","#A1C863"))
colorScale3$col <- as.character(colorScale3$col)
colorScale4 <- data.frame(z=c(0,1),col=c("#76B82b","#76B82b"))
colorScale4$col <- as.character(colorScale4$col)
colorScale5 <- data.frame(z=c(0,1),col=c("#4A731c","#4A731c"))
colorScale5$col <- as.character(colorScale5$col)

f1=list(family = "Arial, sans-serif",
      size = 12,
      color = "#000000")
f2 <- list(family = "Arial, sans-serif",
      size = 14,
      color = "#000000")

plot<-df%>%
  plot_ly(.,y = ~month, x = ~dommapped, z=~group_1, text=~value,name="group1", type="heatmap", xgap=2, ygap=2,hovertemplate=" <extra>%{y}. %{x}: Ø %{text} cases</extra>",
          hoverongaps=FALSE,colorscale=colorScale1,showlegend=TRUE, showscale=FALSE) %>%
  add_trace(.,y = ~month, x = ~dommapped, z=~group_2, text=~value,name="group2", type="heatmap", xgap=2, ygap=2,hovertemplate=" <extra>%{y}. %{x}: Ø %{text} cases</extra>",
            hoverongaps=FALSE,colorscale=colorScale2,showlegend=TRUE, showscale=FALSE) %>%
  add_trace(.,y = ~month, x = ~dommapped, z=~group_3, text=~value,name="group3", type="heatmap", xgap=2, ygap=2,hovertemplate=" <extra>%{y}. %{x}: Ø %{text} cases</extra>",
            hoverongaps=FALSE,colorscale=colorScale3,showlegend=TRUE, showscale=FALSE) %>%
  add_trace(.,y = ~month, x = ~dommapped, z=~group_4, text=~value,name="group4",type="heatmap", xgap=2, ygap=2,hovertemplate=" <extra>%{y}. %{x}: Ø %{text} cases</extra>",
            hoverongaps=FALSE,colorscale=colorScale4,showlegend=TRUE, showscale=FALSE) %>%
  add_trace(.,y = ~month, x = ~dommapped, z=~group_5, text=~value,name="group5", type="heatmap", xgap=2, ygap=2,hovertemplate=" <extra>%{y}. %{x}: Ø %{text} cases</extra>",
            hoverongaps=FALSE,colorscale=colorScale5,showlegend=TRUE, showscale=FALSE)
plot<-plot %>%
  layout(title =list(text= "Very long title about content of graph",
                     xref = "paper",
                     x = 0,
                     font = f2),
         hoverlabel=list(bgcolor="#ffffff",
                         bordercolor ="#ffffff",
                         font=f2),
         showlegend = TRUE,
         separators = ', ',
         plot_bgcolor='#ffffff',
         legend=list(itemclick="toggleothers",
                     orientation="h",
                     title=list(font=f1,
                                text="title"),
                     yanchor="top",
                     y=-0.25),
         modebar = list(color = "#a3a3a3",
                        activecolor = "#000000"),
         xaxis = list(title = "Day of month",
                      zeroline = FALSE,
                      gridcolor = 'ffff',
                      autorange = "reversed",
                      constraintoward="left"),
         yaxis = list(title="month",zeroline = FALSE,gridcolor = 'ffff',autorange = "reversed",
                      scaleanchor="x", constraintoward = "bottom"))

    plot<- plot %>% config(modeBarButtonsToRemove = list('autoScale2d'))
    plot<- plot %>% config(locale='de')
    plot<- plot %>% config(toImageButtonOptions = list(format = "png",filename = "",width = 760,height = 600))
    plot<- plot %>% onRender("function(el, x) {Plotly.d3.select('.cursor-crosshair').style('cursor', 'default')}")
    plot$sizingPolicy$browser$padding <- 0
    htmlwidgets::saveWidget(title = "plot", frameableWidget(plot), "directory/plot_1.html")
</code>```

The scaleanchor and constraintoward commands help to get the design I need. Otherwise the boxes wouldn't be square format.
But it leads - depending on the browser window size - a big white space between graph and title.
Setting the range for the yaxis does not work.
Setting the margin also didn't work so far.

I thought I have to find a solution without scaleanchor and constraintoward to get the needed aspect ratio. So I tried to change the layout by using aspectratio and aspectmode.

```<code>layout(title =list(text= "Very long title about content of graph",
                     xref = "paper",
                     x = 0,
                     font = f2),
         hoverlabel=list(bgcolor="#ffffff",
                         bordercolor ="#ffffff",
                         font=f2),
         showlegend = TRUE,
         separators = ', ',
         plot_bgcolor='#ffffff',
         legend=list(itemclick="toggleothers",
                     orientation="h",
                     title=list(font=f1,
                                text="title"),
                     yanchor="top",
                     y=-0.25),
         modebar = list(color = "#a3a3a3",
                        activecolor = "#000000"),
         xaxis = list(title = "Day of month",
                      zeroline = FALSE,
                      gridcolor = 'ffff',
                      autorange = "reversed"),
         yaxis = list(title="month",zeroline = FALSE,gridcolor = 'ffff',autorange = "reversed"),
         scene=list(aspectmode="manual",
                    aspectratio=list(x=3,
                                     y=1)))

</code>```

But this also didn't work.
I would be happy, if someone has an other idea or solution for this problem.

答:
I figured out a solution for my problem.

By changing in layout for yaxis the key constraintoward to constraintoward = "top" and adding constrain="domain" I get the effect I need.
So the code for the yaxis-layout looks like this:

```<code>layout(yaxis = list(title="month",
                    zeroline = FALSE,
                    gridcolor = 'ffff',
                    autorange = "reversed",
                    scaleanchor="x",
                    constraintoward = "top",
                    constrain="domain"))
</code>```

Body:
I created a kind of interactive calendar heatmap using the following code. It is quite long but should be reproducible.

library(plotly)
library(data.table)
library(tidyr)
library(htmlwidgets)
library(widgetframe)

df <- data.frame(dom = sequence(31,1,1),
             Januar= sample(50:500, 31),
             Februar = sample(50:500, 31),
             März =sample(50:500, 31),
             April = sample(50:500, 31),
             Mai = sample(50:500, 31))

df <- as.data.table(df)
df<- melt(df, id.vars= "dom",variable.name="month",value.name="value", na.rm=T)
df<- as.data.frame(df)
df <- df %>% mutate(month= factor(month,levels=as.character(c("Januar","Februar","März","April","Mai")),labels=c("Jan","Feb","Mär","Apr","Mai"),ordered=TRUE))
df$dommapped <- ordered(df$dom, levels = 31:1)
df <- df%>% mutate(group=ceiling(value/(max(value)/5)))
df$group_1<- ifelse(df$group==1,df$group,NA)
df$group_2<- ifelse(df$group==2,df$group,NA)
df$group_3<- ifelse(df$group==3,df$group,NA)
df$group_4<- ifelse(df$group==4,df$group,NA)
df$group_5<- ifelse(df$group==5,df$group,NA)

colorScale1 <- data.frame(z=c(0,1),col=c("#FFE27a","#FFE27a"))
colorScale1$col <- as.character(colorScale1$col)
colorScale2 <- data.frame(z=c(0,1),col=c("#FFCD0e","#FFCD0e"))
colorScale2$col <- as.character(colorScale2$col)
colorScale3 <- data.frame(z=c(0,1),col=c("#A1C863","#A1C863"))
colorScale3$col <- as.character(colorScale3$col)
colorScale4 <- data.frame(z=c(0,1),col=c("#76B82b","#76B82b"))
colorScale4$col <- as.character(colorScale4$col)
colorScale5 <- data.frame(z=c(0,1),col=c("#4A731c","#4A731c"))
colorScale5$col <- as.character(colorScale5$col)

f1=list(family = "Arial, sans-serif",
      size = 12,
      color = "#000000")
f2 <- list(family = "Arial, sans-serif",
      size = 14,
      color = "#000000")

plot<-df%>%
  plot_ly(.,y = ~month, x = ~dommapped, z=~group_1, text=~value,name="group1", type="heatmap", xgap=2, ygap=2,hovertemplate=" <extra>%{y}. %{x}: Ø %{text} cases</extra>",
          hoverongaps=FALSE,colorscale=colorScale1,showlegend=TRUE, showscale=FALSE) %>%
  add_trace(.,y = ~month, x = ~dommapped, z=~group_2, text=~value,name="group2", type="heatmap", xgap=2, ygap=2,hovertemplate=" <extra>%{y}. %{x}: Ø %{text} cases</extra>",
            hoverongaps=FALSE,colorscale=colorScale2,showlegend=TRUE, showscale=FALSE) %>%
  add_trace(.,y = ~month, x = ~dommapped, z=~group_3, text=~value,name="group3", type="heatmap", xgap=2, ygap=2,hovertemplate=" <extra>%{y}. %{x}: Ø %{text} cases</extra>",
            hoverongaps=FALSE,colorscale=colorScale3,showlegend=TRUE, showscale=FALSE) %>%
  add_trace(.,y = ~month, x = ~dommapped, z=~group_4, text=~value,name="group4",type="heatmap", xgap=2, ygap=2,hovertemplate=" <extra>%{y}. %{x}: Ø %{text} cases</extra>",
            hoverongaps=FALSE,colorscale=colorScale4,showlegend=TRUE, showscale=FALSE) %>%
  add_trace(.,y = ~month, x = ~dommapped, z=~group_5, text=~value,name="group5", type="heatmap", xgap=2, ygap=2,hovertemplate=" <extra>%{y}. %{x}: Ø %{text} cases</extra>",
            hoverongaps=FALSE,colorscale=colorScale5,showlegend=TRUE, showscale=FALSE)
plot<-plot %>%
  layout(title =list(text= "Very long title about content of graph",
                     xref = "paper",
                     x = 0,
                     font = f2),
         hoverlabel=list(bgcolor="#ffffff",
                         bordercolor ="#ffffff",
                         font=f2),
         showlegend = TRUE,
         separators = ', ',
         plot_bgcolor='#ffffff',
         legend=list(itemclick="toggleothers",
                     orientation="h",
                     title=list(font=f1,
                                text="title"),
                     yanchor="top",
                     y=-0.25),
         modebar = list(color = "#a3a3a3",
                        activecolor = "#000000"),
         xaxis = list(title = "Day of month",
                      zeroline = FALSE,
                      gridcolor = 'ffff',
                      autorange = "reversed",
                      constraintoward="left"),
         yaxis = list(title="month",zeroline = FALSE,gridcolor = 'ffff',autorange = "reversed",
                      scaleanchor="x", constraintoward = "bottom"))

    plot<- plot %>% config(modeBarButtonsToRemove = list('autoScale2d'))
    plot<- plot %>% config(locale='de')
    plot<- plot %>% config(toImageButtonOptions = list(format = "png",filename = "",width = 760,height = 600))
    plot<- plot %>% onRender("function(el, x) {Plotly.d3.select('.cursor-crosshair').style('cursor', 'default')}")
    plot$sizingPolicy$browser$padding <- 0
    htmlwidgets::saveWidget(title = "plot", frameableWidget(plot), "directory/plot_1.html")

The scaleanchor and constraintoward commands help to get the design I need. Otherwise the boxes wouldn't be square format.
But it leads - depending on the browser window size - a big white space between graph and title.
Setting the range for the yaxis does not work.
Setting the margin also didn't work so far.

I thought I have to find a solution without scaleanchor and constraintoward to get the needed aspect ratio. So I tried to change the layout by using aspectratio and aspectmode.

layout(title =list(text= "Very long title about content of graph",
                     xref = "paper",
                     x = 0,
                     font = f2),
         hoverlabel=list(bgcolor="#ffffff",
                         bordercolor ="#ffffff",
                         font=f2),
         showlegend = TRUE,
         separators = ', ',
         plot_bgcolor='#ffffff',
         legend=list(itemclick="toggleothers",
                     orientation="h",
                     title=list(font=f1,
                                text="title"),
                     yanchor="top",
                     y=-0.25),
         modebar = list(color = "#a3a3a3",
                        activecolor = "#000000"),
         xaxis = list(title = "Day of month",
                      zeroline = FALSE,
                      gridcolor = 'ffff',
                      autorange = "reversed"),
         yaxis = list(title="month",zeroline = FALSE,gridcolor = 'ffff',autorange = "reversed"),
         scene=list(aspectmode="manual",
                    aspectratio=list(x=3,
                                     y=1)))

But this also didn't work.
I would be happy, if someone has an other idea or solution for this problem.

Body:
I figured out a solution for my problem.

By changing in layout for yaxis the key constraintoward to constraintoward = "top" and adding constrain="domain" I get the effect I need.
So the code for the yaxis-layout looks like this:

layout(yaxis = list(title="month",
                    zeroline = FALSE,
                    gridcolor = 'ffff',
                    autorange = "reversed",
                    scaleanchor="x",
                    constraintoward = "top",
                    constrain="domain"))


问:
Cypress Parallelisation Without Cypress Dashboard
Is there a way I could run parallel cypress executors without access to the cypress dashboard?

I'm trying to have cypress run my tests in parallel but it seems that you must have internet connectivity to reach the cypress dashboard to record the tests.

Anyone knows how I can get around this and have tests run in parallel without being dependent on Cypress Dashboard or a specific CI tool like Circle CI?

Thanks in advance!

答:
I've created a Github Action inspired by the answer of Bielik that allows, among other features, to specify the number of test runners.

Execution consists of two parts:
First, a prepare/install step that splits the tests into specs (best combined with what Cypress Dashbaord needs):

...
- uses: tgamauf/cypress-parallel@v1
```
<p>This provides two output variables <code>integration-tests</code> and if configured <code>component-tests</code>, which can then be used in the test step:</p>
<pre class="lang-js prettyprint-override"><code>    strategy:
      fail-fast: false
      matrix:
        spec: ${{ fromJson(needs.install.outputs.integration-tests) }}
...
      - name: Execute tests
        uses: cypress-io/github-action@v2
        with:
          # We have already installed all dependencies above
          install: false
          # Use the spec provided to this worker to execute the test
          spec: ${{ matrix.spec }}
</code>```

Body:
I've created a Github Action inspired by the answer of Bielik that allows, among other features, to specify the number of test runners.

Execution consists of two parts:
First, a prepare/install step that splits the tests into specs (best combined with what Cypress Dashbaord needs):

...
- uses: tgamauf/cypress-parallel@v1

This provides two output variables integration-tests and if configured component-tests, which can then be used in the test step:

    strategy:
      fail-fast: false
      matrix:
        spec: ${{ fromJson(needs.install.outputs.integration-tests) }}
...
      - name: Execute tests
        uses: cypress-io/github-action@v2
        with:
          # We have already installed all dependencies above
          install: false
          # Use the spec provided to this worker to execute the test
          spec: ${{ matrix.spec }}


问:
How to combine 2 arrays with the condition that 2 and 5 values will be from the second array?
There are two arrays:

```<code>$arrOne = [1, 3, 4];
$arrTwo = [2, 5,];
$newArr = [];
</code>```

How to merge to get like this;

$newArr = [1, 2, 3, 4, 5];

Now displays through one, this option is not suitable.

```<code>foreach ($arrOne as $k => $v) {
 $newArr[] = $v;
 $newArr[] = $arrTwo[$k];
}
</code>```

Here is another example. Tthe values can be different in the array.

```<code>$arrOne = [154, 32, 15];
$arrTwo = [682, 124,];
</code>```

Again for this example it is necessary that the values from the second array always be at 2 and 5 positions in the new array:

```<code>$newArr = [154, 682, 32, 15, 124];
</code>```

答:
```<code>$arrOne = [1, 3, 4];
$arrTwo = [2, 5];
$newArr = [];
foreach($arrOne as $key => $one) {
    switch($key) {
        case 1:
            $newArr[] = $arrTwo[0];
            break;
        case 4:
            $newArr[] = $arrTwo[1];
            break;
    }
    $newArr[] = $one;
}
if(count($newArr) < 5) {
    $newArr[] = $arrTwo[1];
}
</code>```

Demo link

Here we are considering there will be always two elements in second array

Body:
There are two arrays:

$arrOne = [1, 3, 4];
$arrTwo = [2, 5,];
$newArr = [];

How to merge to get like this;

$newArr = [1, 2, 3, 4, 5];

Now displays through one, this option is not suitable.

foreach ($arrOne as $k => $v) {
 $newArr[] = $v;
 $newArr[] = $arrTwo[$k];
}

Here is another example. Tthe values can be different in the array.

$arrOne = [154, 32, 15];
$arrTwo = [682, 124,];

Again for this example it is necessary that the values from the second array always be at 2 and 5 positions in the new array:

$newArr = [154, 682, 32, 15, 124];

Body:
$arrOne = [1, 3, 4];
$arrTwo = [2, 5];
$newArr = [];
foreach($arrOne as $key => $one) {
    switch($key) {
        case 1:
            $newArr[] = $arrTwo[0];
            break;
        case 4:
            $newArr[] = $arrTwo[1];
            break;
    }
    $newArr[] = $one;
}
if(count($newArr) < 5) {
    $newArr[] = $arrTwo[1];
}

Demo link

Here we are considering there will be always two elements in second array


问:
I can't fetch data from Firebase to Vue
I'm following a Youtube tutorial to learn more about storing data in Firebase and then interacting with it in Vue. https://www.youtube.com/watch?v=Htt8AKeF1Kw (at 5:00 is the problem I'm facing)

Basically I follow everything there but the data doesn't show on my vue project and when I open console I see: onUnmounted is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup(). If you are using async setup(), make sure to register lifecycle hooks before the first await statement.

I'm loading 'animes' from Firebase with the following code on firebase.js

```<code>export const loadAnimes = () => {
const animes = ref([])
const close = animeCollection.onSnapshot(snapshot => {
    animes.value = snapshot.docs.map(doc => ({
        id: doc.id, ...doc.data()
    }))
    onUnmounted(close)
    return animes
})
</code>```

From this then I pass it to a component

EDIT: Fixed the issue, it was a mistake on my end, onMounted(close) and return animes should be 2 lines below

```<code>export const loadAnimes = () => {
const animes = ref([])
const close = animeCollection.onSnapshot(snapshot => {
    animes.value = snapshot.docs.map(doc => ({
        id: doc.id, ...doc.data()
    }))
})
onUnmounted(close)
return animes
}
</code>```

答:
Are you sure you wrote it in setup()?

```<code>setup() {
    onUnmounted(() => {
      ...
    })
}```
```

Title: I can't fetch data from Firebase to Vue

Body:
I'm following a Youtube tutorial to learn more about storing data in Firebase and then interacting with it in Vue. https://www.youtube.com/watch?v=Htt8AKeF1Kw (at 5:00 is the problem I'm facing)

Basically I follow everything there but the data doesn't show on my vue project and when I open console I see: onUnmounted is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup(). If you are using async setup(), make sure to register lifecycle hooks before the first await statement.

I'm loading 'animes' from Firebase with the following code on firebase.js

export const loadAnimes = () => {
const animes = ref([])
const close = animeCollection.onSnapshot(snapshot => {
    animes.value = snapshot.docs.map(doc => ({
        id: doc.id, ...doc.data()
    }))
    onUnmounted(close)
    return animes
})

From this then I pass it to a component

EDIT: Fixed the issue, it was a mistake on my end, onMounted(close) and return animes should be 2 lines below

export const loadAnimes = () => {
const animes = ref([])
const close = animeCollection.onSnapshot(snapshot => {
    animes.value = snapshot.docs.map(doc => ({
        id: doc.id, ...doc.data()
    }))
})
onUnmounted(close)
return animes
}

Body:
Are you sure you wrote it in setup()?

setup() {
    onUnmounted(() => {
      ...
    })
}```


问:
Cache the video in Android application
I am developing an android application in which users can see the list of the videos in our database. All the videos are saved in Ooyala video platform.

Now when the user clicks on "download video" button, that video needs to be saved in the application cache. The user can view the video later at anytime. But I need it to be downloaded in the application cache itself, not in the library, so that the user can share that video easily.

So I created a local dababase in the application and saved the video lists.

But I am stuck here, in saving the cache area.

答:
For those of you looking for a Kotlin solution, check this library.

You just need to use

videoView.playUrl("https://your/video/file.mp4")

and the video will be automatically be saved to the local cache and played.

Title: Cache the video in Android application


问:
How does eviction work in a Infinispan replicated cache?
Infinispan supports a type of cache tier called "Replicated" where the content of multiple caches (in different JVMs or even container instances/VMs/servers) are kept (asynchronously) synchronized. My question is how eviction is handled in this case - if a normal local eviction algorithm is used that only looks at one cache it sounds to me like the result would be suboptimal i.e. entries that is not used much in one JVM and therefore are evicted could be the most frequently used one in all the others (that, as I understand it, also will see these entries evicted due to the synchronization between them)...</p>

答:
You will want to check out this section of the Infinispan User Guide https://infinispan.org/docs/stable/titles/configuring/configuring.html#eviction-and-expiration_configuring-memory-usage

As you mentioned eviction is done per node and removes entries that were deemed to be used the least most recently. (Note that off JVM heap and on heap have slightly different algorithms). Due to this it is possible to have some nodes with and without data if you have run out of entries. This in turn can cause inconsistencies with what each node can see.

If you need to limit memory usage, which is the main point of eviction, all you need to do to keep consistency between all nodes is to have a persistent storage defined, such as file store which is covered in the next section https://infinispan.org/docs/stable/titles/configuring/configuring.html#persistence.

Note that expiration differs from eviction in that it is done cluster wide. So if you still want data consistency across all nodes, expiration can be used instead if it is sufficient for your use case.


问:
How to write data from multiple stored procedures to files using SSIS script task?
I have created an SSIS package in SQL Server 2008 that is required to iterate through a table that contains the ID, location to output files, spname to execute and contains data for each clientID within the table. The stored procedures output different reports and contain differing fields this is required to automate the current process of using multiple SSIS package for customer reports, I want to simplify the whole process.

The package I've created contains an SQL script component that saves the data to a variable object, a 'for each container' iterates through the object variable and saves the data to individual variables. However I require assistance with the script task as I can currently connect to the oledb connection manager however the script task is failing when trying to execute the stored procedure, maybe as the data is not output via view or a table.

I am new to VB.NET scripting and don't have that much knowledge of VB.NET, I used the following thread to get to my current position and replaced the dbcommand with an

```<code>Dim query As String = "Exec " & Dts.Variables("User::RunSP").Value
</code>```

I used the following posting to get to my current position:

Exporting data from multiple SQL tables to different flat files using SSIS Script Task

When I execute the script task, it fails at the point where the try and dbconnection is opened. I've tried commenting this out and running the script task without the try section but it has continued to error.

答:
Since you were using the example that I provided as answer to the question Exporting data from multiple SQL tables to different flat files using SSIS Script Task, I took the same example and modified it to run the stored procedure.

It seems to work without any issues. Make sure it matches with what you are trying to do. This example uses SSIS 2005 with SQL Server 2008 R2 database.

Step-by-step process:

Create three tables namely dbo.TablesList, dbo.Source1 and dbo.Source2. Populate the tables with some sample data. Also, create two stored procedures named dbo.SP1 and dbo.SP2. Below given scripts does these tasks to create tables and stored procedures.

```<code>CREATE TABLE [dbo].[Source1](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ItemNumber] [varchar](20) NOT NULL,
    [ItemName] [varchar](50) NOT NULL,
CONSTRAINT [PK_Source1] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Source2](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Country] [varchar](20) NOT NULL,
    [StateProvince] [varchar](50) NOT NULL,
CONSTRAINT [PK_Source2] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO

CREATE TABLE [dbo].[TablesList](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [SPName] [varchar](50) NOT NULL,
    [FilePath] [varchar](255) NOT NULL,
CONSTRAINT [PK_Tables] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO

INSERT INTO dbo.TablesList (FilePath, SPName) VALUES
    ('F:\Temp\Item_Details.txt', 'SP1'),
    ('F:\Temp\Country_StateProvince.txt', 'SP2');
GO

INSERT INTO dbo.Source1 (ItemNumber, ItemName) VALUES
    ('34534', 'Keyboard'),
    ('24312', 'Mouse'),
    ('78555', 'Monitor');
GO

CREATE PROCEDURE [dbo].[SP1]
AS
BEGIN
    SET NOCOUNT ON;

    SELECT * FROM dbo.Source1
END
GO

CREATE PROCEDURE [dbo].[SP2]
AS
BEGIN
    SET NOCOUNT ON;

    SELECT * FROM dbo.Source2
END
GO
</code>```

Data in the tables will look like as shown below in the screenshot.

On the SSIS package, create a connection manager to the SQL Server instance.

On the SSIS package, create 4 variables namely Delimiter, FileName, RunSP and SPsList. Also, place an Execute SQL Task, Foreach Loop container and Script task on the Control Flow tab as shown in the below screenshot.

Configure the Execute SQL task to fetch the list of stored procedures as shown in the below two screenshots.

Configure the Foreach Loop container to loop through the result set stored in the variable SPsList as shown in the below two screenshots.

In the Script task's Script section, click on the Design Script... button to bring the VSTA editor.

Replace the VB.NET code with the below given code. After pasting the code, close the VSTA editor to save the changes.

```<code>Imports System
Imports System.Data
Imports System.Data.OleDb
Imports System.IO
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime

Public Class ScriptMain

    Public Sub Main()

        Dim varCollection As Variables = Nothing

        Dts.VariableDispenser.LockForRead("User::FileName")
        Dts.VariableDispenser.LockForRead("User::Delimiter")
        Dts.VariableDispenser.LockForRead("User::RunSP")
        Dts.VariableDispenser.GetVariables(varCollection)

        Dim fileName As String = varCollection("User::FileName").Value.ToString()
        Dim query As String = "EXEC " & varCollection("User::RunSP").Value.ToString()
        Dim delimiter As String = varCollection("User::Delimiter").Value.ToString()

        Dim writer As StreamWriter = Nothing
        Dim connection As OleDbConnection = New OleDbConnection(Dts.Connections("Learn2008R2").ConnectionString)
        Dim command As OleDbCommand = Nothing
        Dim reader As OleDbDataReader = Nothing

        Try
            If File.Exists(fileName) Then
                File.Delete(fileName)
            End If

            connection.Open()
            command = New OleDbCommand(query, connection)
            reader = command.ExecuteReader()

            writer = New System.IO.StreamWriter(fileName)

            Dim row As Integer = 0
            Dim header As Integer = 0
            Dim fieldCount As Integer = reader.FieldCount - 1

            If row = 0 Then
                While header <= fieldCount
                    If header <> fieldCount Then
                        writer.Write(reader.GetName(header).ToString() & delimiter)
                    Else
                        writer.WriteLine(reader.GetName(header).ToString())
                    End If
                    header += 1
                End While
            End If

            If reader.HasRows Then
                While reader.Read()
                    Dim counter As Integer = 0
                    While counter <= fieldCount
                        If counter <> fieldCount Then
                            writer.Write(reader(counter).ToString() & delimiter)
                        Else
                            writer.WriteLine(reader(counter).ToString())
                        End If
                        counter += 1
                    End While
                End While
            End If
        Catch ex As Exception
            Throw ex
        Finally
            connection.Close()
            writer.Close()
        End Try

        Dts.TaskResult = Dts.Results.Success

    End Sub

End Class
</code>```

Contents of the folder F:\Temp before executing the package. The folder is empty.

Successful package execution is shown in the below screenshot.

Folder path F:\Temp now contains the two files that were generated by the Script Task inside the package using the data provided by the individual stored procedures SP1 and SP2.

Contents of the files are shown in the below screenshots. The file contents are pipe delimited and you can notice the data matches with the table data shown in the earlier screenshot.

Hope that helps.

Body:
I have created an SSIS package in SQL Server 2008 that is required to iterate through a table that contains the ID, location to output files, spname to execute and contains data for each clientID within the table. The stored procedures output different reports and contain differing fields this is required to automate the current process of using multiple SSIS package for customer reports, I want to simplify the whole process.

The package I've created contains an SQL script component that saves the data to a variable object, a 'for each container' iterates through the object variable and saves the data to individual variables. However I require assistance with the script task as I can currently connect to the oledb connection manager however the script task is failing when trying to execute the stored procedure, maybe as the data is not output via view or a table.

I am new to VB.NET scripting and don't have that much knowledge of VB.NET, I used the following thread to get to my current position and replaced the dbcommand with an

Dim query As String = "Exec " & Dts.Variables("User::RunSP").Value

I used the following posting to get to my current position:

Exporting data from multiple SQL tables to different flat files using SSIS Script Task

When I execute the script task, it fails at the point where the try and dbconnection is opened. I've tried commenting this out and running the script task without the try section but it has continued to error.

Body:
Since you were using the example that I provided as answer to the question Exporting data from multiple SQL tables to different flat files using SSIS Script Task, I took the same example and modified it to run the stored procedure.

It seems to work without any issues. Make sure it matches with what you are trying to do. This example uses SSIS 2005 with SQL Server 2008 R2 database.

Step-by-step process:

Create three tables namely dbo.TablesList, dbo.Source1 and dbo.Source2. Populate the tables with some sample data. Also, create two stored procedures named dbo.SP1 and dbo.SP2. Below given scripts does these tasks to create tables and stored procedures.

CREATE TABLE [dbo].[Source1](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ItemNumber] [varchar](20) NOT NULL,
    [ItemName] [varchar](50) NOT NULL,
CONSTRAINT [PK_Source1] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Source2](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Country] [varchar](20) NOT NULL,
    [StateProvince] [varchar](50) NOT NULL,
CONSTRAINT [PK_Source2] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO

CREATE TABLE [dbo].[TablesList](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [SPName] [varchar](50) NOT NULL,
    [FilePath] [varchar](255) NOT NULL,
CONSTRAINT [PK_Tables] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO

INSERT INTO dbo.TablesList (FilePath, SPName) VALUES
    ('F:\Temp\Item_Details.txt', 'SP1'),
    ('F:\Temp\Country_StateProvince.txt', 'SP2');
GO

INSERT INTO dbo.Source1 (ItemNumber, ItemName) VALUES
    ('34534', 'Keyboard'),
    ('24312', 'Mouse'),
    ('78555', 'Monitor');
GO

CREATE PROCEDURE [dbo].[SP1]
AS
BEGIN
    SET NOCOUNT ON;

    SELECT * FROM dbo.Source1
END
GO

CREATE PROCEDURE [dbo].[SP2]
AS
BEGIN
    SET NOCOUNT ON;

    SELECT * FROM dbo.Source2
END
GO

Data in the tables will look like as shown below in the screenshot.

On the SSIS package, create a connection manager to the SQL Server instance.

On the SSIS package, create 4 variables namely Delimiter, FileName, RunSP and SPsList. Also, place an Execute SQL Task, Foreach Loop container and Script task on the Control Flow tab as shown in the below screenshot.

Configure the Execute SQL task to fetch the list of stored procedures as shown in the below two screenshots.

Configure the Foreach Loop container to loop through the result set stored in the variable SPsList as shown in the below two screenshots.

In the Script task's Script section, click on the Design Script... button to bring the VSTA editor.

Replace the VB.NET code with the below given code. After pasting the code, close the VSTA editor to save the changes.

Imports System
Imports System.Data
Imports System.Data.OleDb
Imports System.IO
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime

Public Class ScriptMain

    Public Sub Main()

        Dim varCollection As Variables = Nothing

        Dts.VariableDispenser.LockForRead("User::FileName")
        Dts.VariableDispenser.LockForRead("User::Delimiter")
        Dts.VariableDispenser.LockForRead("User::RunSP")
        Dts.VariableDispenser.GetVariables(varCollection)

        Dim fileName As String = varCollection("User::FileName").Value.ToString()
        Dim query As String = "EXEC " & varCollection("User::RunSP").Value.ToString()
        Dim delimiter As String = varCollection("User::Delimiter").Value.ToString()

        Dim writer As StreamWriter = Nothing
        Dim connection As OleDbConnection = New OleDbConnection(Dts.Connections("Learn2008R2").ConnectionString)
        Dim command As OleDbCommand = Nothing
        Dim reader As OleDbDataReader = Nothing

        Try
            If File.Exists(fileName) Then
                File.Delete(fileName)
            End If

            connection.Open()
            command = New OleDbCommand(query, connection)
            reader = command.ExecuteReader()

            writer = New System.IO.StreamWriter(fileName)

            Dim row As Integer = 0
            Dim header As Integer = 0
            Dim fieldCount As Integer = reader.FieldCount - 1

            If row = 0 Then
                While header <= fieldCount
                    If header <> fieldCount Then
                        writer.Write(reader.GetName(header).ToString() & delimiter)
                    Else
                        writer.WriteLine(reader.GetName(header).ToString())
                    End If
                    header += 1
                End While
            End If

            If reader.HasRows Then
                While reader.Read()
                    Dim counter As Integer = 0
                    While counter <= fieldCount
                        If counter <> fieldCount Then
                            writer.Write(reader(counter).ToString() & delimiter)
                        Else
                            writer.WriteLine(reader(counter).ToString())
                        End If
                        counter += 1
                    End While
                End While
            End If
        Catch ex As Exception
            Throw ex
        Finally
            connection.Close()
            writer.Close()
        End Try

        Dts.TaskResult = Dts.Results.Success

    End Sub

End Class

Contents of the folder F:\Temp before executing the package. The folder is empty.

Successful package execution is shown in the below screenshot.

Folder path F:\Temp now contains the two files that were generated by the Script Task inside the package using the data provided by the individual stored procedures SP1 and SP2.

Contents of the files are shown in the below screenshots. The file contents are pipe delimited and you can notice the data matches with the table data shown in the earlier screenshot.

Hope that helps.


问:
Get project output path from csproj file
Is it possible, from code, to get some project's output path from its vb/csproj alone? I am using .Net framework (4.8). I could not find anything exactly matching what I am looking for. There is https://learn.microsoft.com/en-us/dotnet/api/microsoft.build.evaluation.project.getpropertyvalue?view=msbuild-17-netcore but this isn't available in the .Net framework.

EDIT

I am coding an output builder, which takes targeted assemblies of a solution projects and copy them in a specified location.

答:
The code below uses MSBuild to get the properties of a csproj file specified as a string, and retrieves the current TargetPath. If you create a Console App in .NET Framework 4.8 it will get the output library path of a .NET Framework project.</p>
```<code>using Microsoft.Build.Evaluation;
using System;
using System.Collections.Generic;
using System.Linq;

namespace PathGetter
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string testCsproj = @"C:\Dotnet\WpfControlLibrary1\WpfControlLibrary1\WpfControlLibrary1.csproj";
            string result = GetProperty(testCsproj, "TargetPath");
            Console.WriteLine(result);
        }

        public static string GetProperty(string csproj, string propertyName)
        {
           using (var collection = new ProjectCollection())
            {
                var project = new Project(csproj, new Dictionary<string, string>(),
                    null, collection, ProjectLoadSettings.Default);
                return project.Properties.Where(p => p.Name == propertyName)
                    .Select(p => p.EvaluatedValue).SingleOrDefault();
            }
        }
    }
}
</code>```

Body:
The code below uses MSBuild to get the properties of a csproj file specified as a string, and retrieves the current TargetPath. If you create a Console App in .NET Framework 4.8 it will get the output library path of a .NET Framework project.

using Microsoft.Build.Evaluation;
using System;
using System.Collections.Generic;
using System.Linq;

namespace PathGetter
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string testCsproj = @"C:\Dotnet\WpfControlLibrary1\WpfControlLibrary1\WpfControlLibrary1.csproj";
            string result = GetProperty(testCsproj, "TargetPath");
            Console.WriteLine(result);
        }

        public static string GetProperty(string csproj, string propertyName)
        {
           using (var collection = new ProjectCollection())
            {
                var project = new Project(csproj, new Dictionary<string, string>(),
                    null, collection, ProjectLoadSettings.Default);
                return project.Properties.Where(p => p.Name == propertyName)
                    .Select(p => p.EvaluatedValue).SingleOrDefault();
            }
        }
    }
}


问:
Best Practice for multiple asp.net web applications
Looking for the best practice when having multiple web applications within one ASP.NET "site" or "solution". I have a few options I am toying with:

old faithful of putting all applications and Site master into one Solution / one web application

My boss is worried about having 30 'applications' that are all under the same project in VS and every time we make a change to one have to deploy to all. So this makes us want to break out each into a separate project under the same solution. This makes us have to look into Master page solutions

Master page needs to support dynamic menu structure. Is this something that I can do with a single SiteMaster? Does VirtualProvider provide the right solution for this? Anyone have any good tutorials on it?

Creating a UserControl for each application and reference it in the main application

答:
I asked two similar questions here:

Cross-Project Master Page

Best bet is separate projects under a single solution and use Nuget package to synch up the common artifacts, including master pages. Right now this is working fine on a 22 project solution I'm working on. You can also store the Nuget package itself in source control.

Update:

You could use an XML file for your menu and share it out with Nuget. Possibly add jQuery for a sliding effect, etc.


问:
How to get raspberry's stats in python code
I would like to retrieve the stats (Ram, storage, ...) of my raspberry pi in a python code but I can't find how. An idea ?</p>

答:
Consider using the psutil library to assist you with this.

Have a look at the below code snippet which I copied verbatim from this page:

```<code>import psutil

# Get cpu statistics
cpu = str(psutil.cpu_percent()) + '%'

# Calculate memory information
memory = psutil.virtual_memory()
# Convert Bytes to MB (Bytes -> KB -> MB)
available = round(memory.available/1024.0/1024.0,1)
total = round(memory.total/1024.0/1024.0,1)
mem_info = str(available) + 'MB free / ' + str(total) + 'MB total ( ' + str(memory.percent) + '% )'

# Calculate disk information
disk = psutil.disk_usage('/')
# Convert Bytes to GB (Bytes -> KB -> MB -> GB)
free = round(disk.free/1024.0/1024.0/1024.0,1)
total = round(disk.total/1024.0/1024.0/1024.0,1)
disk_info = str(free) + 'GB free / ' + str(total) + 'GB total ( ' + str(disk.percent) + '% )'

print("CPU Info–> ", cpu)
print("Memory Info–>", mem_info)
print("Disk Info–>", disk_info)
</code>```

Body:
Consider using the psutil library to assist you with this.

Have a look at the below code snippet which I copied verbatim from this page:

import psutil

# Get cpu statistics
cpu = str(psutil.cpu_percent()) + '%'

# Calculate memory information
memory = psutil.virtual_memory()
# Convert Bytes to MB (Bytes -> KB -> MB)
available = round(memory.available/1024.0/1024.0,1)
total = round(memory.total/1024.0/1024.0,1)
mem_info = str(available) + 'MB free / ' + str(total) + 'MB total ( ' + str(memory.percent) + '% )'

# Calculate disk information
disk = psutil.disk_usage('/')
# Convert Bytes to GB (Bytes -> KB -> MB -> GB)
free = round(disk.free/1024.0/1024.0/1024.0,1)
total = round(disk.total/1024.0/1024.0/1024.0,1)
disk_info = str(free) + 'GB free / ' + str(total) + 'GB total ( ' + str(disk.percent) + '% )'

print("CPU Info–> ", cpu)
print("Memory Info–>", mem_info)
print("Disk Info–>", disk_info)