TestNG listener, how to get the singleton use by the tests - parallel-processing

We use the TestNG listener feature to report the results of our tests in an external tool. It works fine.
But now, we want to add an information contained by a singleton (a ThreadLocal webdriver). Our test campaign is run in parallel, so we have multiple instance of our singleton.
How can we in the method onSuccess for instance get the correct singleton and so report the correct information?
Edit: code sample
public class QTestWrapper implements ISuiteListener, ITestListener {
...
#Override
public void onTestSuccess(ITestResult result) {
String sessionId = MyDriver.getSessionId();
// do my job with this session id
}
...
}
public final class MyDriver {
private static final ThreadLocal<MyDriver> MY_DRIVER =
ThreadLocal.withInitial(MyDriver::buildDriver);
private WebDriver driver;
private MyDriver(WebDriver driver) {
this.driver = driver;
}
public static MyDriver getDriver() {
return MY_DRIVER.get();
}
private static MyDriver buildDriver() {
URL remoteAddress = getHubAddress();
DesiredCapabilities caps = buildCapabilities();
WebDriver driver = new RemoteWebDriver(remoteAddress, caps);
return new MyDriver(driver);
}
public static String getSessionId() {
String sessionId = null;
MyDriver driver = MY_DRIVER.get();
if (driver != null && driver.getWrappedDriver() != null) {
WebDriver wrappedDriver = driver.getWrappedDriver();
sessionId = ((RemoteWebDriver) wrappedDriver).getSessionId().toString();
}
return sessionId;
}
public WebDriver getWrappedDriver() {
return driver;
}
}
public class TestLogin {
#AfterMethod(alwaysRun = true)
public void die() {
StickyDriver.quit();
}
#Test(description = "Check that a user can login with a Manager profile.")
public void loginAsManager() {
Actor actor = new Actor("foo");
String userName = actor.openBrowserAndLogin().getUserName();
assertThat(userName).isEqualTo("foo");
}
}
public class Actor {
private static final Logger LOGGER = LogManager.getLogger();
private final MyDriver driver;
private User user;
public Actor(String userName) {
user = User.getUser(userName);
driver = MyDriver.getDriver();
}
public Actor(User user) {
this.user = Objects.requireNonNull(user);
driver = MyDriver.getDriver();
}
public HomePage openBrowserAndLogin() {
openBrowser();
return login();
}
public HomePage login() {
LoginPage loginPage = new LoginPage(driver);
loginPage.getUserNameField().setValue(user.getUsername());
loginPage.getPasswordField().setValue(user.getPassword());
return loginPage.login();
}
private void openBrowser() {
String url = EnvironmentHelper.getUrl();
WebDriver webDriver = driver.getWrappedDriver();
webDriver.get(url);
try {
new WebDriverWait(webDriver, 60).until(AjaxExpectedConditions.callsHaveCompleted());
} catch (TimeoutException ex) {
closeBrowser();
throw ex;
}
}
public void closeBrowser() {
MyDriver.quit();
}
}

TestNG does not guarantee that the #Test and onSuccess() will be executed in the same thread.
That assurance is only provided when you work with org.testng.IInvokedMethodListener implementation.
So please change your implementation to do the following :
Have your class QTestWrapper implement org.testng.IInvokedMethodListener
within the afterInvocation() of org.testng.IInvokedMethodListener check if the method that got executed was a #Test method and if its status was a pass, and if it passed you move your logic within onSuccess() into it.

Related

Register DynamicParameterizedType global

How can i register a global available DynamicParameterizedType in hibernate?
I wrote the following type:
public class QuantityType extends AbstractSingleColumnStandardBasicType<Quantity<?>> implements DynamicParameterizedType {
public static final QuantityType INSTANCE = new QuantityType();
public QuantityType() {
super(DoubleTypeDescriptor.INSTANCE, new QuantityJavaDescriptor(AbstractUnit.ONE));
}
#Override
public String getName() {
return QuantityType.class.getSimpleName();
}
#Override
public void setParameterValues(Properties parameters) {
ParameterType reader = (ParameterType) parameters.get(PARAMETER_TYPE);
if (reader == null) throw new RuntimeException("Not Implemented");
Unit<?> resolvedUnit = resolveUnit(reader);
setJavaTypeDescriptor(new QuantityJavaDescriptor(resolvedUnit));
}
private Unit<?> resolveUnit(ParameterType reader) {...}
}
and registered it with a service registration in hibernate:
public class QuantityTypeRegistration implements TypeContributor {
#Override
public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
typeContributions.contributeType(QuantityType.INSTANCE);
}
}
If i use the type in an entity, the wrap/unwrap method of the JavaTypeDescriptor gets called,
but instead of the parameterized JavaTypeDescriptor, the default JavaTypeDescriptor gets called. For some reason the setParameterValues method was not called.
Code: https://github.com/raynigon/unit-api/tree/master/jpa-starter/src/main/java/com/raynigon/unit_api/jpa

Read data from an Android Room database in a background Service, no exceptions but no data

I am attempting to read data from an Android Room database in a background Service. There are no exceptions but no data is returned.
I wrote a function to select all rows from a table in the DAO. Calling that function from a background service succeeds, but it returns no data.
My "Contact" class holds contact information (names, phone numbers, emails) and defines the database schema. The database holds rows of contacts, with names, phone numbers, an emails as columns.
The function that returns the LiveData in the DAO is:
#Query("SELECT * FROM contacts_table")
LiveData<List<Contact>> getAll();
where "contacts_table" is the database table holding contact information.
I called getAll as follows:
AppDatabase db = AppDatabase.getDatabase(messageSenderContext.getApplicationContext());
mContactDAO = db.contactDAO();
mAllContacts = mContactDAO.getAll();
where mContactDao is a ContactDAO (The Database Access Object for my Contact class), and mAllContacts is a LiveData>. These are private fields of the class calling getAll().
db.contactDAO() returns an object, as does mContactDAO.getAll(). But attempting to unpack the List from mAllContacts using mAllContacts.getValue() returns null.
This turned out to be a misuse of LiveData. That requires an Observer to actually get the data.
In your ROOM
#Database(entities={Contact.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public static final String DATABASE_NAME = "AppDatabase.db";
private static volatile AppDatabase INSTANCE;
private static final int NUMBER_OF_THREADS = 4;
public static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(NUMBER_OF_THREADS);
public abstract ContactDAO contactDAO();
public static AppDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (AppDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, DATABASE_NAME)
.build();
}
}
}
return INSTANCE;
}
}
In your DAO
#Dao
public interface ContactDAO{
#Query("SELECT * FROM contacts_table")
LiveData<List<Contact>> getAll();
}
In your repository:
public class AppRepository {
private ContactDAO mContactDAO;
//constructor
public AppRepository(Application application) {
AppDatabase db = AppDatabase.getDatabase(application);
mContactDAO= db.contactDAO();
}
public LiveData<List<Contact>> getAllContacts(){
LiveData<List<Contact>> contactsList = null;
Future<LiveData<List<Contact>>> futureList = AppDatabase.EXECUTOR_SERVICE.submit(new Callable(){
#Override
public LiveData<List<Contact>> call() {
return contactDAO.getAll();
}
});
try {
contactsList = futureList.get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return contactsList ;
}
}
In your ViewModel
public class ContactsViewModel extends AndroidViewModel {
private AppRepository appRepository;
private LiveData<List<Contact>> contactsList;
public ContactsViewModel(#NonNull Application application) {
super(application);
appRepository = new AppRepository(application);
}
public LiveData<List<Contacts>> list() {
return appRepository.getAllContacts();
}
}
In your activity (inside of onCreated put)
ContactsViewModel contactsViewModel = new ViewModelProvider(this).get(ContactsViewModel.class);
contactsViewModel.list().observe(getViewLifecycleOwner(), new Observer<List<Contact>>() {
#Override
public void onChanged(List<Contact> contactsList) {
//the contact list will be observed and will return data if there are changes.
//use for example to feed the adapter of a recyclerview
//below an example just to view the contacts data
for(Contact conctact : contactsList){
Log.d("TestApp>>>", "Id: + contact.getId);
Log.d("TestApp>>>", "Name: + contact.getName);
}
});

Spring Boot class cast exception in PostConstruct method

I am running a Spring Boot application with a PostConstruct method to populate a POJO before application initialization. This is to ensure that the database isn't hit by multiple requests to get the POJO content after it starts running.
I'm able to pull the data from Oracle database through Hibernate query and store it in my POJO. The problem arises when I try to access the stored data. The dataset contains a list of objects that contain strings and numbers. Just trying to print the description of the object at the top of the list raises a class cast exception. How should I mitigate this issue?
#Autowired
private TaskDescrBean taskBean;
#PostConstruct
public void loadDescriptions() {
TaskDataLoader taskData = new TaskDataLoader(taskBean.acquireDataSourceParams());
List<TaskDescription> taskList = tdf.getTaskDescription();
taskBean.setTaskDescriptionList(taskList);
System.out.println("Task description size: " + taskBean.getTaskDescriptionList().get(0).getTaskDescription());
}
My POJO class:
#Component
public class TaskDescrBean implements ApplicationContextAware {
#Resource
private Environment environment;
protected List<TaskDescription> taskDescriptionList;
public Properties acquireDataSourceParams() {
Properties dataSource = new Properties();
dataSource.setProperty("hibernate.connection.driver_class", environment.getProperty("spring.datasource.driver-class-name"));
dataSource.setProperty("hibernate.connection.url", environment.getProperty("spring.datasource.url"));
dataSource.setProperty("hibernate.connection.username", environment.getProperty("spring.datasource.username"));
dataSource.setProperty("hibernate.connection.password", environment.getProperty("spring.datasource.password"));
return dataSource;
}
public List<TaskDescription> getTaskDescriptionList() {
return taskDescriptionList;
}
public void setTaskDescriptionList(List<TaskDescription> taskDescriptionList) {
this.taskDescriptionList = taskDescriptionList;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
}
My DAO class:
public class TaskDataLoader {
private Session session;
private SessionFactory sessionFactory;
public TaskDataLoader(Properties connectionProperties) {
Configuration config = new Configuration().setProperties(connectionProperties);
config.addAnnotatedClass(TaskDescription.class);
sessionFactory = config.buildSessionFactory();
}
#SuppressWarnings("unchecked")
public List<TaskDescription> getTaskDescription() {
List<TaskDescription> taskList = null;
session = sessionFactory.openSession();
try {
String description = "from TaskDescription des";
Query taskDescriptionQuery = session.createQuery(description);
taskList = taskDescriptionQuery.list();
System.out.println("Task description fetched. " + taskList.getClass());
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
return taskList;
}
TaskDescription Entity:
#Entity
#Table(name="TASK_DESCRIPTION")
#JsonIgnoreProperties
public class TaskDescription implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="TASK_DESCRIPTION_ID")
private Long taskDescriptionId;
#Column(name="TASK_DESCRIPTION")
private String taskDescription;
public Long getTaskDescriptionId() {
return taskDescriptionId;
}
public void setTaskDescriptionId(Long taskDescriptionId) {
this.taskDescriptionId = taskDescriptionId;
}
public String getTaskDescription() {
return taskDescription;
}
public void setTaskDescription(String taskDescription) {
this.taskDescription = taskDescription;
}
}
StackTrace
Instead of sending the List in the return statement, I transformed it into a JSON object and sent its String representation which I mapped back to the Object after transforming it using mapper.readValue()

PostConstruct is called twice

I use,
JSF
Spring
OCPSoft Rewrite
Glassfish 4 / Jetty 9
I've noticed that my beans invoke #PostConstruct's init() method twice. Here's sample bean that got initialized twice, if you'll need web.xml or anything else, just post it - I ran out of ideas.
#ManagedBean(name = "userBean")
public class UserBean implements Serializable {
private static final long serialVersionUID = -1347081883455053542L;
#ManagedProperty(value = "#{param.username}")
private String username;
private Users user;
private Authentication authentication;
private StreamedContent avatar;
#PostConstruct
public void init() {
System.out.println("userbean init and username: " + username);
user = Users.findByUsername(username);
authentication = SecurityContextHolder.getContext()
.getAuthentication();
if (user == null) {
Navigator.redirect("/601");
return;
}
if (user.isKeepPrivate() == true && !username.equals(authentication.getName())) {
Navigator.redirect("/600");
return;
}
avatar = new DefaultStreamedContent(UserUtils.getAvatar(user), "image/png");
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public StreamedContent getAvatar() {
return avatar;
}
public void setAvatar(StreamedContent avatar) {
this.avatar = avatar;
}
}
we have this problem here, but is a problem with WebSphere 6. (runaway from websphere :D)
So... we do a little workaround to use #PostConstruct...
Maybe can help you...
public boolean firstInit() {
boolean firstInit= false;
try {
FacesContext context = FacesContext.getCurrentInstance();
firstInit= context != null && context.getExternalContext().getRequestParameterMap().containsKey(ResponseStateManager.VIEW_STATE_PARAM);
} catch (Exception e) {
firstInit= false;
}
return firstInit;
}
public void init(){
if (firstInit()) return;
//init methods
}
And #PostConstruct method called twice for the same request this can help you too...
obs: i cant write comments :/

smartgwt listgrid RestDataSource not populating

Im new using this front end framework application...
I recently started to work with smartgwt and i'm bulding a new application with a Spring MVC integration.
I'm using a ListGrid with a RestDataSource (Consume the Rest service with mvc:annotation-driven for plain JSON)
I can see that the servaice gets consuming properly perhaps my grid is never shown with the data in it.
Can someone help me here ?
Here's my ListGrid class
public class ListGrid extends com.smartgwt.client.widgets.grid.ListGrid {
private final SpringJSONDataSource springJSONDataSource;
public ListGrid(List<DataSourceField> fields) {
this(new PatientDataSource(fields));
}
public ListGrid(SpringJSONDataSource springJSONDataSource) {
this.springJSONDataSource = springJSONDataSource;
init();
}
private void init() {
setAutoFetchData(true);
setAlternateRecordStyles(true);
setEmptyCellValue("???");
setDataPageSize(50);
setDataSource(springJSONDataSource);
}
}
Now there's the DataSource implmentation
public abstract class SpringJSONDataSource extends RestDataSource {
protected final HTTPMethod httpMethod;
public SpringJSONDataSource(List<DataSourceField> fields) {
this(fields, HTTPMethod.POST);
}
public SpringJSONDataSource(List<DataSourceField> fields, HTTPMethod httpMethod) {
this.httpMethod = httpMethod;
setDataFormat(DSDataFormat.JSON);
addDataSourceFields(fields);
setOperationBindings(getFetch());
addURLs();
}
private void addURLs() {
if(getUpdateDataURL() != null)
setUpdateDataURL(getUpdateDataURL());
if(getRemoveDataURL() != null)
setRemoveDataURL(getRemoveDataURL());
if(getAddDataURL() != null)
setAddDataURL(getAddDataURL());
if(getFetchDataURL() != null)
setFetchDataURL(getFetchDataURL());
}
private void addDataSourceFields(List<DataSourceField> fields) {
for (DataSourceField dataSourceField : fields) {
addField(dataSourceField);
}
}
protected abstract OperationBinding getFetch();
protected abstract OperationBinding getRemove();
protected abstract OperationBinding getAdd();
protected abstract OperationBinding getUpdate();
public abstract String getUpdateDataURL();
public abstract String getRemoveDataURL();
public abstract String getAddDataURL();
public abstract String getFetchDataURL();
}
The class PatientDataSource that extends SpringJSONDataSource
public class PatientDataSource extends SpringJSONDataSource {
public PatientDataSource(List<DataSourceField> fields) {
super(fields);
setPrettyPrintJSON(true);
}
#Override
protected OperationBinding getFetch() {
OperationBinding fetch = new OperationBinding();
fetch.setOperationType(DSOperationType.FETCH);
fetch.setDataProtocol(DSProtocol.POSTMESSAGE);
DSRequest fetchProps = new DSRequest();
fetchProps.setHttpMethod(httpMethod.toString());
fetch.setRequestProperties(fetchProps);
return fetch;
}
#Override
public String getFetchDataURL() {
return "/spring/fetchPatients";
}
#Override
protected OperationBinding getRemove() {
return null;
}
#Override
public String getRemoveDataURL() {
return null;
}
#Override
protected OperationBinding getAdd() {
return null;
}
#Override
public String getAddDataURL() {
return null;
}
#Override
protected OperationBinding getUpdate() {
return null;
}
#Override
public String getUpdateDataURL() {
return null;
}
}
My spring controller PatientControler
#Controller
public class PatienController {
Logger logger = Logger.getLogger(PatienController.class);
#Autowired
private PatientServices patientServices;
#RequestMapping(value = "/patientTest", method = RequestMethod.GET)
#ResponseBody
public Object getTest()
{
return patientServices.getAllPatients();
}
#RequestMapping(value = "/fetchPatients", method = RequestMethod.POST)
#ResponseBody
public Object getAllPatients()
{
return patientServices.getAllPatients();
}
}
PatientServiceImpl
public class PatientServicesImpl implements PatientServices {
public List<Patient> getAllPatients() {
List<Patient> patients = new ArrayList<Patient>();
Patient patient;
for(int i = 0 ; i < 500 ; i++){
patient = new Patient();
patient.setDateOfBirth(new Date());
patient.setFirstName("Joe");
patient.setMiddleName("Moe");
patient.setLastName("Blow");
patient.setLastConsultation(new Date());
patient.setSex(Sex.M);
patients.add(patient);
}
return patients;
}
}
*Im Really stuck right now i've been looking for all type of answers .... but so far nothing worked when i tried to override the transformResponse from my RestDataSource impentation the parameter "data" as an OBJECT, returns me an array [object Object],[object Object],[object Object],[object Object],[object Object] *
The Data which is transferred from the RestDataSource has a specific format which is described in the JavaDoc of the RestDataSource
Your server must understand the request and send back a valid response.
At the moment your example doesn't seem to honour the contract.
To debug the traffic send to and from your server you can use the SmartClient-Console. You can open it by a browser bookmark like this:
javascript:isc.showConsole()
Of cause you need to deploy this console by adding the following module to your gwt.xml
<inherits name="com.smartclient.tools.SmartClientTools"/>
Now go to the RPC Tab and check Track-RPCs

Resources