Spring DataSource with embedded HSQL in memory database and hibernate create-drop ordering on Linux - linux

I am using Spring 3.1 with annotations to create a DataSource that uses embedded HSQL.
#Bean
public DataSource dataSource() throws Exception {
EmbeddedDatabaseFactoryBean bean = new EmbeddedDatabaseFactoryBean();
bean.setDatabaseType(EmbeddedDatabaseType.HSQL);
bean.afterPropertiesSet();
DataSource object = bean.getObject();
return object;
}
I am also configuring a SessionFactory like this
#Bean
public SessionFactory sessionFactory() {
SessionFactory sessionFactory = new LocalSessionFactoryBuilder(dataSource)
.setNamingStrategy(namingStrategy())
.addProperties(hibernateProperties)
.addAnnotatedClass(Some.class)
.buildSessionFactory();
logger.info("Created session factory: " + sessionFactory + " with dataSource: " + dataSource);
return sessionFactory;
}
The problem is if I create some other beans using #Component in which I populate the database, the SQL script fails because the database has not been created. My hibernate.properties includes the following line to generate DDL
properties.put("hibernate.hbm2ddl.auto", "create-drop");
So it is some sort of ordering issue with bean creating. However this problem only occurs in Linux (Kubuntu 12.04) and not on Windows 7!

I have worked out that in my #Component bean which populates the database I had to add the #DependsOn annotation like this
#Component
#DependsOn({"dataSource", "sessionFactory"})
public class DevSqlPopulator {
...
}

I think the issue is that you are calling a InitializingBean method afterPropertiesSet method yourself instead of letting Spring call it once all the properties are cleanly set. Try doing this instead:
#Bean
public EmbeddedDatabaseFactoryBean dataSource() throws Exception {
EmbeddedDatabaseFactoryBean bean = new EmbeddedDatabaseFactoryBean();
bean.setDatabaseType(EmbeddedDatabaseType.HSQL);
return bean;
}
Now it is a clean factory bean and Spring will take care of the rest of the lifecycle.

Related

Flowable bpmn access Spring beans inside groovy script

We are setting up a flowable application to use multiple bpmns with reusable java delegates. In application.yml, we have properties set for each bpmn
e.g.
app1.mail.active: true
app2.mail.active: false
ApplicationProperties file is set with #ConfigurationProperties() to get the properties.
Created a Spring bean:
#Bean("applicationProperties")
public ApplicationProperties applicationProperties(){
return new ApplicationProperties();
}
I am trying to use a script task using groovy and initialize the appropriate properties. It seems Spring beans are not available inside the script.
<scriptTask id="sid-C8B8BE3F-F6CB-4559-B48C-5BC14AB76494" name="Initialize Process" scriptFormat="groovy">
<script><![CDATA[
// I want to be able to access applicationProperties bean here
def _properties = applicationProperties.getApp1()
execution.setVariable("properties", _properties)
]]></script>
</scriptTask>
When initializing bpmn for app1, I want to set a variable for properties related to app1 and similar to app2. I am able to use existing spring beans elsewhere in the same bpmn but not inside groovy script task.
Thank you in advance.
The solution that I came up was to create a service task with java delegate to initialize application properties and common variables based on the bpmn instance and set a properties variable, then as part of the same service task I added an executionListener to set variables that are specific to that instance, using groovy script.
<serviceTask id="initProcess" name="Init Process" flowable:delegateExpression="${initProcessDelegate}">
<extensionElements>
<flowable:executionListener event="end" class="org.flowable.engine.impl.bpmn.listener.ScriptExecutionListener">
<flowable:field name="script">
<flowable:string><![CDATA[
import config.ApplicationProperties;
ApplicationProperties.Props props = (ApplicationProperties.Props) execution.getVariable("properties");
System.out.println("properties " + properties.getUrl());
]]></flowable:string>
</flowable:field>
<flowable:field name="language">
<flowable:string><![CDATA[groovy]]></flowable:string>
</flowable:field>
</flowable:executionListener>
</extensionElements>
</serviceTask>
public class ProcessInitDelegate implements JavaDelegate {
Logger log = LoggerFactory.getLogger(getClass());
#Autowired
ApplicationProperties applicationProperties;
public void execute(DelegateExecution execution) {
log.info("<--------------- ProcessInitDelegate ------------->");
try {
// set up properties for current instance
String instance = (String) execution.getVariable("processInstance");
Object properties = applicationProperties.getInnerInstance(instance);
if (instance.equals("<your_instance_name>")) {
ApplicationProperties.Props instanceProperties = (ApplicationProperties.Props) properties;
execution.setVariable("properties, instanceProperties);
}
} catch (Exception e) {
log.error("Error setting up process {} ", e.getMessage());
}
}
}
You can swop over to SecureJavaScript and add the bean to the trusted beans in your custom config.
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-secure-javascript</artifactId>
<version>6.6.0</version>
</dependency>
#Bean
public SecureJavascriptConfigurator secureJavascriptConfigurator() {
SecureJavascriptConfigurator configurator =
new SecureJavascriptConfigurator()
.setMaxStackDepth(10)
.setMaxScriptExecutionTime(3000L)
.setMaxMemoryUsed(3145728L)
.setNrOfInstructionsBeforeStateCheckCallback(10)
.setEnableAccessToBeans(true);
return configurator;
}
#Bean
#ConditionalOnClass(SpringProcessEngineConfiguration.class)
public EngineConfigurationConfigurer<SpringProcessEngineConfiguration> customProcessEngineConfigurer() {
return configuration -> {
configuration.addConfigurator(secureJavascriptConfigurator());
Map<Object, Object> beans = new HashMap<>();
beans.put("applicationProperties", applicationProperties);
configuration.setBeans(beans);
};
}

Integrating Activiti with JSF

Am trying to start activiti engine from jsf
#ManagedBean(name = "activitiProcess")
#ViewScoped
public class ActivitiProcess implements Serializable {
private String filename = "D:/WORKSPACE/activiti1/src/main/resources/diagrams/MyProcess.bpmn";
public ActivitiProcess() {
}
public void startProcess() {
System.out.println("hello world");
try {
ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); //returns null
RepositoryService repositoryService = engine.getRepositoryService();
repositoryService.createDeployment().addInputStream("myProcess.bpmn20.xml", new FileInputStream(filename)).deploy();
RuntimeService runtimeService = engine.getRuntimeService();
ProcessDefinition definition = engine.getRepositoryService().createProcessDefinitionQuery().processDefinitionKey("myProcess").singleResult();
FormService formService = engine.getFormService();
// List<FormProperty> formList = formService.getStartFormData(definition.getId()).getFormProperties();
Map<String, String> formProperties = new HashMap<String, String>();
/* use the jsf variable instead */
formProperties.put("filePath", "D://somePath");
formService.submitStartFormData(definition.getId(), formProperties);
} catch (Exception e) {
e.printStackTrace();
}
}
}
the engine always returns as null , I read that the activiti.cfg.xml file should be in the class path , I've put the file under web-inf/classes but still , engine returns null which means activiti can't initialize the engine , any ideas ?
add this
#Inject
private ProcessEngine engine;
if you want to run a CDI Bean inside a container, you are not allowed to use the new keyword. Instead, you need to inject the bean and the container does the
rest, meaning, the container is the one responsible for managing the life cycle of the bean: it creates the instance; it gets rid of it. So how do you initialize a bean if you can’t call a constructor? Well, the container gives you a handle after constructing an instance and before destroying it.

Injecting a service inside of TimerTask

I need to run daily a process in order to do maintenance work on the server (update records).
I have a singleton scope class that runs a timer and an inner class with the injection of the service I need. When I run the programm the timer throws a NullPointerException because the service has not been injected.
#Named("demonService")
#Singleton
public class DemonImpl implements IDemonService
{
private static Logger log = Logger.getLogger(DemonioImpl.class);
#PostConstruct
public void init()
{
log.info("-->Demon");
Calendar today = new GregorianCalendar();//Every day at 2:00am (from now)
today.set(Calendar.HOUR_OF_DAY, 2);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
try
{
Timer timer = new Timer(true);
timer.schedule(new Updater(), today.getTime(), 24*60*60*1000);
}
catch(Exception e)
{
log.fatal(e.getLocalizedMessage());
e.printStackTrace();
}
log.info("--> Demon: exit");
}
private class Updater extends TimerTask
{
private Logger log = Logger.getLogger(Updater.class);
#Inject
#Named("updaterService")
private IUpdaterService updaterService;
#Override
public void run()
{
log.info("Task: update records (start)");
List<Record> list = updaterService.getAll();//<-- This throws the exception
for(Record item : list)
{
updaterService.update(item);
}
log.info("Task: update records (exit)");
}
}
The error is
Exception in thread "Timer-3" java.lang.NullPointerException
at test.service.impl.DemonImpl$Updater.run(DemonImpl.java:66)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
The application works fine except for this class. How can I inject the service when the application is fully working?
Normally you have a NPE when the Class is not a CDI Bean. If you make new Updater() this is not considered by CDI. you have to #Inject the Updater in your Singleton.
CDI won't manage the instance since you instantiate your Updater by calling the constructor of it yourself.
Now there are two ways to fix this:
Inject an instance of the Updater class in DemonImpl and use that one.
Create a new CDI managed instance at runtime by injecting a Provider<Updater> instance in DemonImpl and get a new instance of the Updater class from it.

Junit4 Mockito UnfinishedVerificationException TransactionManager

i'm just running into a complicated Problem as i began to unit-Test some Controller-Methods in a Spring FW4 based Java Application.
My ApplicationConfig.java is annotated with #Configuration and #EnableTransactionManagement(proxyTargetClass = true) and a public Controller method, which i created to save a new object of a simple entity-class is testet with the following ControllerTestClass
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(locations = {"classpath:/test-context.xml"})
#TransactionConfiguration(defaultRollback = true, transactionManager = "annotationDrivenTransactionManager")
public class TestController
#Autowired
public MyClassService myClassServiceMock;
protected MockMvc mockMvc;
#Autowired
protected WebApplicationContext webApplicationContext;
#Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
};
#org.junit.Before
public void reset() {
Mockito.reset(myClassServiceMock);
}
#org.junit.After
public void after() {
verifyNoMoreInteractions(myClassServiceMock);
}
#Test
public void testSaveObject() throws Exception {
MyObject object = new MyObjectBuilder().withName("object").withDate("2014-08-15").build();
when(myClassServiceMock.createObject(objectName, objectDate)).thenReturn(object);
[.. mockMvcTest which works ... ]
verify(myclassServiceMock, times(1)).createObject(objectName, objectDate);
}
}
The following part of the debug.log is something I can't figure out the reason for the problem, but when i remove the #EnableTransactionManager-Annotation, no error occures...
2014-08-15_17:25:59.608 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Creating new transaction with name [a.b.c.MyClassService$$EnhancerByMockitoWithCGLIB$$cf62a86c.saveObject]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2014-08-15_17:25:59.608 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Opened new EntityManager [org.hibernate.jpa.internal.EntityManagerImpl#513f39c] for JPA transaction
2014-08-15_17:25:59.616 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle#320cac01]
2014-08-15_17:25:59.618 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Initiating transaction commit
2014-08-15_17:25:59.618 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Committing JPA transaction on EntityManager [org.hibernate.jpa.internal.EntityManagerImpl#513f39c]
2014-08-15_17:25:59.633 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Closing JPA EntityManager [org.hibernate.jpa.internal.EntityManagerImpl#513f39c] after transaction
2014-08-15_17:25:59.633 [main] DEBUG o.s.o.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
2014-08-15_17:25:59.635 [main] DEBUG o.s.t.c.s.DirtiesContextTestExecutionListener - After test method: context [DefaultTestContext#8f72029 testClass = MyControllerTest, testInstance = a.b.c.MyControllerTest#453204e6, testMethod = testSaveObject#MyClassControllerTest, testException = org.mockito.exceptions.misusing.UnfinishedVerificationException:
Missing method call for verify(mock) here:
-> at a.b.c.MyClassService$$FastClassBySpringCGLIB$$809f2bf.invoke(<generated>)
Example of correct verification:
verify(mock).doSomething()
I would really appreciate some help, because my oddisee and research already is going on for a couple of days :(
Thanks
Firstly, you aren't initializing Mockito in your tests. Read this post
You need to call MockitoAnnotations.initMocks() because you are already using #RunWith(SpringJUnit4ClassRunner.class) and you can only specify one runner on a Class.
#Before
public void reset() {
MockitoAnnotations.initMocks(this);
// Mockito.reset(myClassServiceMock); <= remove this line
}
I think you also want to use #Mock instead of #Autowired for this mock so that you have an instance of a Mockito mock that you can then call verify() on later. You will also have to inject myClassServiceMock into your class under test (i.e. the Controller)
#Mock
public MyClassService myClassServiceMock;
You can remove the call to Mockito.reset() as #Mock will create a new instance for each test method.
If you were intending to use #Autowired and retrieve the instance of MyClassService from your application context then you won't be able to call any Mockito methods like verify() on it.
I would also expect that #TransactionConfiguration is not required because you are never hitting your database (because you are mocking out your service layer), so you can remove it. If you are hitting your database in your test, then that's a different story, but I can't tell that from the code you have provided.

accessing jsf bean from blazeds client

How can I access a jsf managed bean (say, icefaces) from a blazeds client?
Will it be possible to share the same session information also ? (for eg, if I have a page with a jsf/icefaces component and a swf client - can they use the same session?)
first of all you have to implement the FlexFactory in your own Factory:
http://livedocs.adobe.com/blazeds/1/blazeds_devguide/factory_2.html
I change the SpringFactory a little bit so you can access to the current instance of the given bean:
public class BeanFactory implements FlexFactory {
private static final String SOURCE = "source";
public void initialize(String id, ConfigMap configMap) {}
public FactoryInstance createFactoryInstance(String id, ConfigMap properties) {
BeanFactoryInstance instance = new BeanFactoryInstance(this, id, properties);
instance.setSource(properties.getPropertyAsString(SOURCE, instance.getId()));
return instance;
}
public Object lookup(FactoryInstance inst) {
BeanFactoryInstance factoryInstance = (BeanFactoryInstance) inst;
return factoryInstance.lookup();
}
static class BeanFactoryInstance extends FactoryInstance {
BeanFactoryInstance(BeanFactory factory, String id, ConfigMap properties) {
super(factory, id, properties);
}
public String toString() {
return "BeanFactory instance for id=" + getId() + " source=" + getSource() + " scope=" + getScope();
}
public Object lookup() {
HttpServletRequest hsr = FlexContext.getHttpRequest();
String beanName = getSource();
try
{
Object o = hsr.getSession().getAttribute(beanName);
return o;
}
catch (Exception e)
{
ServiceException se = new ServiceException();
String msg = "Java Bean '" + beanName + "' does not exist.";
se.setMessage(msg);
se.setRootCause(e);
se.setDetails(msg);
se.setCode("Server.Processing");
throw se;
}
}
}}
in the service-config.xml (WEB-INF/flex folder) you have to register this factory:
<factories>
<factory id="beanFactory" class="packageName.BeanFactory"/>
</factories>
then you have to register the factory in your destination in the remoting-config.xml like this:
<destination id="remoteService">
<properties>
<factory>beanFactory</factory>
<source>beanName</source>
<scope>session</scope>
</properties>
</destination>
so what is this BeanFactory doing:
when you want to access per remote from flex to java or to the jee-application, you declare a remoteobject in flex with the destination "remoteService" which is configured in the remoting-config.xml. the moment you access from flex to java by calling a server-sided-method, the beanfactory looks after the current instance of the bean you declare in the remoting-config.xml by getting the Request over the FlexContext:
HttpServletRequest hsr = FlexContext.getHttpRequest();
now you get the session and with the beanName the instance by callinghsr.getSession().getAttribute(beanName)
this is only working with application and session beans and only if jsf instantiated the bean before the BeanFactory want to access the bean...
when you want to integrate a swf-file with icefaces you should take the ice:outputMedia-Tag an set the player-attribute to "flash"
if you work with eclipse to develop your jee-application and you integrate the tomcat in eclipse you can set the server root folder in the properties of your flex-project to the tomcat folder (flex builder):
(Sorry not time for making this looks good ;) )
now you can start the tomcat server directly in eclipse and you can debug on flex and java too :)
hope this helps!

Resources