PostConstruct is called twice - spring

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 :/

Related

TestNG listener, how to get the singleton use by the tests

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.

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()

Axon Event Handler not Working

I am developing a small cqrs implementation and I am very new to it.
I want to segregate each handlers(Command and Event) from aggregate and
make sure all are working well. The command handler are getting triggered
from controller but from there event handlers are not triggered. Could
anyone Please help on this.
public class User extends AbstractAnnotatedAggregateRoot<String> {
/**
*
*/
private static final long serialVersionUID = 1L;
#AggregateIdentifier
private String userId;
private String userName;
private String age;
public User() {
}
public User(String userid) {
this.userId=userid;
}
#Override
public String getIdentifier() {
return this.userId;
}
public void createuserEvent(UserCommand command){
apply(new UserEvent(command.getUserId()));
}
#EventSourcingHandler
public void applyAccountCreation(UserEvent event) {
this.userId = event.getUserId();
}
}
public class UserCommand {
private final String userId;
public UserCommand(String userid) {
this.userId = userid;
}
public String getUserId() {
return userId;
}
}
#Component
public class UserCommandHandler {
#CommandHandler
public void userCreateCommand(UserCommand command) {
User user = new User(command.getUserId());
user.createuserEvent(command);
}
}
public class UserEvent {
private final String userId;
public UserEvent(String userid) {
this.userId = userid;
}
public String getUserId() {
return userId;
}
}
#Component
public class UserEventHandler {
#EventHandler
public void createUser(UserEvent userEvent) {
System.out.println("Event triggered");
}
}
#Configuration
#AnnotationDriven
public class AppConfiguration {
#Bean
public SimpleCommandBus commandBus() {
SimpleCommandBus simpleCommandBus = new SimpleCommandBus();
return simpleCommandBus;
}
#Bean
public Cluster normalCluster() {
SimpleCluster simpleCluster = new SimpleCluster("simpleCluster");
return simpleCluster;
}
#Bean
public ClusterSelector clusterSelector() {
Map<String, Cluster> clusterMap = new HashMap<>();
clusterMap.put("com.user.event.handler", normalCluster());
//clusterMap.put("exploringaxon.replay", replayCluster());
return new ClassNamePrefixClusterSelector(clusterMap);
}
#Bean
public EventBus clusteringEventBus() {
ClusteringEventBus clusteringEventBus = new ClusteringEventBus(clusterSelector(), terminal());
return clusteringEventBus;
}
#Bean
public EventBusTerminal terminal() {
return new EventBusTerminal() {
#Override
public void publish(EventMessage... events) {
normalCluster().publish(events);
}
#Override
public void onClusterCreated(Cluster cluster) {
}
};
}
#Bean
public DefaultCommandGateway commandGateway() {
return new DefaultCommandGateway(commandBus());
}
#Bean
public Repository<User> eventSourcingRepository() {
EventStore eventStore = new FileSystemEventStore(new SimpleEventFileResolver(new File("D://sevents.txt")));
EventSourcingRepository eventSourcingRepository = new EventSourcingRepository(User.class, eventStore);
eventSourcingRepository.setEventBus(clusteringEventBus());
AnnotationEventListenerAdapter.subscribe(new UserEventHandler(), clusteringEventBus());
return eventSourcingRepository;
}
}
As far as I can tell, the only thing missing is that you aren't adding the User Aggregate to a Repository. By adding it to the Repository, the User is persisted (either by storing the generated events, in the case of Event Sourcing, or its state otherwise) and all Events generated by the Command Handler (including the Aggregate) are published to the Event Bus.
Note that the Aggregate's #EventSourcingHandlers are invoked immediately, but any external #EventHandlers are only invoked after the command handler has been executed.

Can't evict from Spring Cache in Guice DI app

I'm trying to use String Cache abstraction mechanism with guice modules.
I've created interceptors:
CacheManager cacheManager = createCacheManager();
bind(CacheManager.class).toInstance(cacheManager);
AppCacheInterceptor interceptor = new AppCacheInterceptor(
cacheManager,
createCacheOperationSource()
);
bindInterceptor(
Matchers.any(),
Matchers.annotatedWith(Cacheable.class),
interceptor
);
bindInterceptor(
Matchers.any(),
Matchers.annotatedWith(CacheEvict.class),
interceptor
);
Then, implemented Strings Cache interface and CacheManager, and finally annotated my DAO classes with #Cachable and #CacheEvict:
public class DaoTester {
QssandraConsumer qs;
#CachePut(value = "cached_consumers", key = "#consumer.id")
public void save(QssandraConsumer consumer) {
qs = consumer;
}
#Cacheable(value = "cached_consumers")
public QssandraConsumer get(String id) {
if (id != null) {
qs.getId();
}
return qs;
}
#CacheEvict(value = "cached_consumers", key = "#consumer.id")
public void remove(QssandraConsumer consumer) {
qs = consumer;
}}
Caching is simply fine - no problems here, but when i try to evict(calling remove method in this example), evrything crashes and I see:
Exception in thread "main" org.springframework.expression.spel.SpelEvaluationException: EL1007E:(pos 10): Field or property 'id' cannot be found on null
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:205)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:72)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:93)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:88)
at org.springframework.cache.interceptor.ExpressionEvaluator.key(ExpressionEvaluator.java:80)
at org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.generateKey(CacheAspectSupport.java:464)
at org.springframework.cache.interceptor.CacheAspectSupport.inspectCacheEvicts(CacheAspectSupport.java:260)
at org.springframework.cache.interceptor.CacheAspectSupport.inspectAfterCacheEvicts(CacheAspectSupport.java:232)
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:215)
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:66)
at qiwi.qommon.deployment.dao.DaoTester.main(DaoTester.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
What's wrong here?!
BTW, cached object is:
public class QssandraConsumer implements Identifiable<String> {
private String id;
private String host;
#Override
public String getId() {
return id;
}
#Override
public void setId(String id) {
this.id = id;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
#Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (null == object) {
return false;
}
if (!(object instanceof QssandraConsumer)) {
return false;
}
QssandraConsumer o = (QssandraConsumer) object;
return
Objects.equal(id, o.id)
&& Objects.equal(host, o.host);
}
#Override
public int hashCode() {
return Objects.hashCode(
id, host
);
}
#Override
public String toString() {
return Objects.toStringHelper(this)
.addValue(id)
.addValue(host)
.toString();
}
}
Finally I figured out what was the reason of the problem:
when injecting a class that uses annotation(which are intercepted, like #Cachable or #CacheEvict) Guice enhances class (AOP make bytecode modification in runtime). So when CacheInterceptor tryed to evaluate key = "#consumer.id" it failed because couldn't find argument name in enhanced class (see: LocalVariableTableParameterNameDiscoverer#inspectClass).
So it will not work in Guice out of the box.
In spring the proxy class is created - so no problems here.

Cannot delete entity (JPA & Spring)

What ever I try, I cannot delete a user entity when I call delete() from my userService class. I get an exception java.lang.IllegalArgumentException: Entity must be managed to call remove: com.blackbox.genesis.entities.User#30168a, try merging the detached and try the remove again. I'm obviously doing something wrong - despite merging, but I can't see what. Everything else works fine - I can create and update user entities without any problem.
Regards
My entity class;
#Entity
#Table(uniqueConstraints = {#UniqueConstraint(columnNames = "EMAIL")})
public class User implements Serializable {
#Id
#Column(name="username", length=50)
private String username;
#OneToOne(cascade = {CascadeType.ALL})
private Password password;
private boolean enabled;
private int serial;
private String email;
#Version
private int version;
#ElementCollection(targetClass=Authority.class)
#CollectionTable(name="USER_AUTHORITY")
private List<Authority> authorities;
#OneToMany(mappedBy="user", fetch=FetchType.LAZY, cascade=CascadeType.ALL, ``orphanRemoval=true)
private Set<License> licenses;
private static final long serialVersionUID = 1L;
public User() {
super();
this.authorities = new ArrayList<Authority>();
}
.... getters/setters.
My DAO class;
#Repository
public class UserJpaController {
#PersistenceContext
EntityManager em;
protected static final Logger logger = Logger.getLogger("com.blackbox.genesisng.entities.UsersJpaController");
public void create(User user) throws PreexistingEntityException, Exception {
if (findUser(user.getUsername()) != null) {
throw new PreexistingEntityException("Users " + user + " already exists.");
}
em.persist(user);
em.flush();
}
public void edit(User user) throws NonexistentEntityException, Exception {
user = em.merge(user);
em.flush();
}
public void destroy(String id) throws NonexistentEntityException {
User user = em.find(User.class, id);
user = em.merge(user);
em.remove(user);
}
public List<User> findUserEntities() {
return findUserEntities(true, -1, -1);
}
public List<User> findUserEntities(int maxResults, int firstResult) {
return findUserEntities(false, maxResults, firstResult);
}
private List<User> findUserEntities(boolean all, int maxResults, int firstResult) {
Query q = em.createQuery("select object(o) from User as o");
if (!all) {
q.setMaxResults(maxResults);
q.setFirstResult(firstResult);
}
return q.getResultList();
}
public User findUser(String id) {
return em.find(User.class, id);
}
public int getUserCount() {
Query q = em.createQuery("select count(o) from User as o");
return ((Long) q.getSingleResult()).intValue();
}
public User findUserByEmail(String email) {
Query q = em.createQuery("select Object(o) from User as o where o.email = :email");
q.setParameter("email", email);
List list = q.getResultList();
if (list.size() == 0) {
return null;
}
return (User) list.get(0);
}
public boolean exists(String id) {
try {
em.getReference(User.class,id);
return true;
}
catch (EntityNotFoundException e) {
return false;
}
}
}
and finally, the relevant portion of my service class
#Service
public class UserService {
#Autowired
UserJpaController dao;
#Autowired
LicenseJpaController licenseDao;
#Transactional
public void delete(UserDTO userDTO) {
if (exists(userDTO.getUserName())){
try {
dao.destroy(userDTO.getUserName());
} catch (NonexistentEntityException e) {
// ignore as the previous test should prevent this.
}
}
}
So sorry, but I'm an idiot! I was not calling the service class that I thought I was. Fixed that and everything works as expected. Once again, sorry folks.
Regards
Remove the
user = em.merge(user);
statement in your DAO destroy method. I am not sure if it causes the probem, but it is not needed because the user is loaded in the statement before.

Resources