I've a bean named textFileWriter to write string entities to HDFS. I've configured the spring bean in bean config file. While executing am getting NullPointerException. Please help me on this.
My bean configuration :-
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/hadoop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:hdp="http://www.springframework.org/schema/hadoop" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/hadoop http://www.springframework.org/schema/hadoop/spring-hadoop.xsd">
<hdp:configuration id="hadoopConfigBean">
fs.defaultFS=${hdp.fs}
</hdp:configuration>
<beans:bean id="textFileWriter"
class="org.springframework.data.hadoop.store.output.TextFileWriter">
<beans:constructor-arg index="0" ref="hadoopConfigBean"></beans:constructor-arg>
<beans:constructor-arg index="1"
type="org.apache.hadoop.fs.Path" value="/user/mhduser"></beans:constructor-arg>
<beans:constructor-arg index="2" type="org.springframework.data.hadoop.store.codec.CodecInfo" >
<beans:null></beans:null>
</beans:constructor-arg>
</beans:bean>
<context:property-placeholder location="hadoop-configs.properties" />
</beans:beans>
Main Class :-
public class MainApp {
#Autowired
TextFileWriter textFileWriter;
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext(
"/META-INF/spring/application-context.xml", MainApp.class);
System.out.println("Context loaded...");
MainApp obj=new MainApp();
obj.someMethod();
context.registerShutdownHook();
}
private void someMethod() {
try {
textFileWriter.write("hi there");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Am getting null pointer exception in this line :-
textFileWriter.write("hi there");
You can still make Spring inject dependencies without adding MainApp as a bean explicitly.
Enable annotation driven config. Add to the application-context.xml following
<context:annotation-config />
Make Spring wire dependencies with
MainApp obj=new MainApp();
context.getAutowireCapableBeanFactory().autowireBean(obj);
#Autowired won't work here because you are using a new instance of class MainApp which is not managed by spring and that's why you are getting a NullPointerException
MainApp obj=new MainApp();
obj.someMethod();
A work around would be :
public class MainApp {
public MainApp(TextFileWriter textFileWriter){
this.textFileWriter = textFileWriter;
}
public MainApp(){
}
#Autowired
TextFileWriter textFileWriter;
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"/META-INF/spring/application-context.xml");
System.out.println("Context loaded...");
TextFileWriter textFileWriter = (TextFileWriter ) context.getBean("textFileWriter");
MainApp obj=new MainApp(textFileWriter );
obj.someMethod();
context.registerShutdownHook();
}
private void someMethod() {
try {
textFileWriter.write("hi there");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Related
I developed the application using spring transactions and insert records in the table.
I'm explicitly throwing the exception in DAO class but spring is inserting the record into the table rather than roll back the transaction.
I have created the two applications as below . In Case 1 record is inserted into table even though exception is thrown . But In Case 2 no record is inserted and spring roll back the transaction successfully. Can you explain me the difference between these two applications.
Case 1:
Item.java
public class Item {
int itemNo;
String itemName;
String itemType;
String itemSize;
public int getItemNo() {
return itemNo;
}
public void setItemNo(int itemNo) {
this.itemNo = itemNo;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public String getItemType() {
return itemType;
}
public void setItemType(String itemType) {
this.itemType = itemType;
}
public String getItemSize() {
return itemSize;
}
public void setItemSize(String itemSize) {
this.itemSize = itemSize;
}
}
ItemDao
#Service
public class ItemDao {
#Autowired
JdbcTemplate jdbcTemplate ;
void insert(Item item){
jdbcTemplate.update("insert into item_test(itemno, itemtype,itemsize,itemname) values (?,?,?,?)", new Object[]{item.getItemNo(),item.getItemType(),item.getItemSize(),item.getItemName()});
int a=2/0;
}
}
ItemService.java
#Service
public class ItemService {
#Autowired
ItemDao itemDao;
#Transactional
public void insert(Item item){
try{
itemDao.insert(item);
}
catch(Exception e){
e.printStackTrace();
}
}
}
Test.java
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ct = new ClassPathXmlApplicationContext("spring.xml");
ItemService itemService = ct.getBean("itemService", ItemService.class);
Item item = new Item();
item.setItemNo(1234);
item.setItemName("sofa");
item.setItemSize("4");
item.setItemType("furniture");
itemService.insert(item);
}
}
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Enable Annotation based Declarative Transaction Management -->
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />
<context:component-scan base-package="com.spring.springtransaction" />
<!-- Creating TransactionManager Bean, since JDBC we are creating of type
DataSourceTransactionManager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- MySQL DB DataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#locahost:1521:xe)))" />
<property name="username" value="system" />
<property name="password" value="system" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="itemService" class="com.spring.springtransaction.ItemService" />
</beans>
Case 2:
ItemService.java
#Service
public class ItemService {
#Autowired
ItemDao itemDao;
#Autowired
ItemManger itemManger;
#Transactional
public void insert(Item item){
try{
itemManger.insert(item);
}
catch(Exception e){
e.printStackTrace();
}
}
}
ItemManger.java
#Service
public class ItemManger {
#Autowired
ItemDao itemDao;
#Transactional
public void insert(Item item){
itemDao.insert(item);
}
}
ItemDao.java
#Service
public class ItemDao {
#Autowired
JdbcTemplate jdbcTemplate ;
void insert(Item item){
jdbcTemplate.update("insert into item_test(itemno, itemtype,itemsize,itemname) values (?,?,?,?)", new Object[]{item.getItemNo(),item.getItemType(),item.getItemSize(),item.getItemName()});
int a=2/0;
}
}
Annotate you ItemDao as #Repository instead of #Service
You should execute unit test with spring Transactional context instead of main , for example using TestNG:
#ContextConfiguration(classes = {ConfigurationClass.class})
#ActiveProfiles({"test"})
public class TestItemDAO extends AbstractTransactionalTestNGSpringContextTests {
#Autowired
private ItemDao dao;
#Test
public void testItemDao() {
dao.insert(item);
}
}
Remove the try block, you are trying to handle the exception so this is reason why RollbackException is not cutting the transaction stream.
I'm currently experimenting on bean callback methods and noticed that if I define callback methods for one bean, these methods are also called on other beans.
I have a classes named x.HelloWorld (no callbacks) and y.HelloWorld (has init and destroy callback methods).
HelloWorld.java:
public class HelloWorld {
private String message;
public void setMessage(String message) {
this.message = message;
}
public void getMessage() {
System.out.println("Your Message : " + message);
}
}
HelloWorld2.java:
public class HelloWorld {
private String message;
public void setMessage(String message) {
this.message = message;
}
public void getMessage() {
System.out.println("Your Message : " + message);
}
public void init() {
System.out.println("Bean is going through init.");
}
public void destroy() {
System.out.println("Bean will destroy now.");
}
}
x.MainApp.java:
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.getMessage();
}
}
y.MainApp.java:
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld2");
obj.getMessage();
context.registerShutdownHook();
}
}
beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<bean id="helloWorld" class="x.HelloWorld">
<property name="message" value="Hello World (1)" />
</bean>
<bean id="helloWorld2" class="y.HelloWorld"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World (2)" />
</bean>
</beans>
Results:
Running y.MainApp (works as expected):
Bean is going through init.
Your Message : Hello World (2)
Bean will destroy now.
Running x.MainApp (the init callback of x.HelloWorld is triggered by y.HelloWorld. Confused of this one.. any help is very much appreciated...)
Bean is going through init.
Your Message : Hello World (1)
Please modify your init method like this:
public void init() {
System.out.println("Bean with message '"+ message +"' is going through init.");
}
You will see that all beans are initialized at startup and that the message you see actually comes from the class with the init method.
If you don't want this behavior you can use lazy init:
<bean id="helloWorld2" class="y.HelloWorld"
init-method="init" destroy-method="destroy" lazy-init="true">
I'm trying to intercept any method tagged w/ a custom annotation and the reason you read this is because I can't get it to work. I've been following simple examples but can't get it to work.
Here is my code.
MyAnnotation.java:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface MyAnnotation {
String value() default "";
String key() default "";
String condition() default "";
}
MyAspect.java:
#Aspect
public class MyAspect {
#Pointcut(value="execution(public * *(..))")
public void anyPublicMethod() { }
#Around("anyPublicMethod() && #annotation(myAnnotation)")
public Object process(ProceedingJoinPoint jointPoint, MyAnnotation myAnnotation) throws Throwable {
System.out.println("In AOP process");
return 5; //jointPoint.proceed();
}
}
spring-config.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-3.2.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.2.xsd">
...
<context:component-scan base-package="com.myapp">
<context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="myAspect" class="com.myapp.annotation.MyAspect" />
...
MyComponent.java:
#Component
public class MyComponent {
#MyAnnotation(value="valtest", key="keytest", condition="contest")
public int add(int i, int j) {
System.out.println("Executing annotation.add");
return i+j;
}
}
Test code:
final MyComponent m = new MyComponent();
assertTrue(5 == m.add(0, 1)); // Here m.add(...) always returns 1 instead of 5.
As a side note I've tried to define my pointcut many different ways, all with and without the use of the anyPublic() method and its execution pointcut, but none of those worked for me:
#Around("#annotation(com.myapp.annotation.MyAnnotation)")
public Object process(ProceedingJoinPoint jointPoint) throws Throwable { .. }
#Around(value="#annotation(myAnnotation)", argNames="myAnnotation")
public Object process(ProceedingJoinPoint jointPoint, MyAnnotation myAnnotation) throws Throwable { .. }
#Around("execution(* com.myapp.*.*(..)) && #annotation(com.myapp.annotation.MyAnnotation)")
public Object process(ProceedingJoinPoint jointPoint) throws Throwable { .. }
What am I doing wrong?
In your test code, you are not allowing Spring to create your MyComponent, but instead, you are using the new operator. You should be accessing MyComponent from Spring's ApplicationContext.
public class SomeTest {
public static void main(String[] args) throws Exception {
final ApplicationContext appContext = new ClassPathXmlApplicationContext("spring-config.xml");
final MyComponent myComponent = appContext.getBean(MyComponent.class);
//your test here...
}
}
If you do not get your component from Spring, how do you expect it to be proxied?
I use Spring with Hibernate and get always a NPE for the sessionFactory Object.
My config file:
#Configuration
public class HibernateConfiguration {
#Bean
public AnnotationSessionFactoryBean sessionFactory() {
Properties props = new Properties();
props.put("hibernate.dialect", MySQL5InnoDBDialect.class.getName());
props.put("hibernate.format_sql", "true");
props.put("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
props.put("hibernate.connection.password", "xxx");
props.put("hibernate.connection.url", "jdbc:mysql://localhost/Market");
props.put("hibernate.connection.username", "philipp");
AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean();
bean.setAnnotatedClasses(new Class[] { xxx.class, xxx.class, xxx.class });
bean.setHibernateProperties(props);
bean.setSchemaUpdate(true);
return bean;
}
#Bean
public HibernateTransactionManager transactionManager() {
return new HibernateTransactionManager(sessionFactory().getObject());
}
#Bean
public PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
My DAOImpl class:
#Repository("xxx")
public class xxxDAOImpl implements xxxDAO {
private SessionFactory sessionFactory;
#Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private Session currentSession() {
return sessionFactory.getCurrentSession();
}
...
Testcase:
#ContextConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
public class TestxxxDAOImpl {
#Test
#Transactional
public void testInsertxxx() throws Exception {
xxxDAO xxxDAO = new xxxDAOImpl();
xyz xyz = new xyz();
xxxDAO.insert(xyz);
assertNotNull(xyz.getId());
}
}
app-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="xxx.config" />
<context:component-scan base-package="xxx.dao" />
<context:annotation-config></context:annotation-config>
test-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<import resource="classpath:/META-INF/spring/app-context.xml" />
I get always an NPE from the currentSession when the test calls the insert method.
public void insert(xxx xxx) {
currentSession().save(xxx);
}
private Session currentSession() {
return sessionFactory.getCurrentSession();
}
The very first thing to understand when working with Spring is that Spring dependency injection only works for beans obtained from the application context, not for beans created with new.
In Spring-enabled unit tests you configure application context using #ContextConfiguration, for example, as follows (works in Spring 3.1, in previous versions #ContextConfiguration doesn't take #Configuration classes directly, therefore you'll have to create XML configuration file):
#Configuration
public class HibernateConfiguration {
// Add your DAO to application context
#Bean
public xxxDAO xxxDAO() {
return new xxxDAOImpl();
}
...
}
// Configure application context using the given #Configuration class
#ContextConfiguration(classes = HibernateConfiguration.class)
#RunWith(SpringJUnit4ClassRunner.class)
public class TestxxxDAOImpl {
// Obtain DAO from the application context
#Autowired xxxDao xxxDao;
...
}
Instead of sessionFactory.getCurrentSession() in currentSession() function of xxxDAOImpl class, use sessionFactory.openSession().
Since in your first call there would not be any current session in the session factory so you need to open the session.
Hope this helps you. Cheers.
I'm using Spring 3.1.0.RELEASE. I'm having trouble autowiring a private variable from a Spring4JUnitRunner class. My JUnit class is ...
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({ "file:src/main/webapp/WEB-INF/dispatcher-servlet.xml" })
public class RegistrationControllerTest {
#Autowired
private ApplicationContext applicationContext;
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private HandlerAdapter handlerAdapter;
private RegistrationController controller;
#Before
public void setUp() {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
handlerAdapter = applicationContext.getBean(HandlerAdapter.class);
// I could get the controller from the context here
controller = new RegistrationController();
final RegistrationValidation registrationValidation = new RegistrationValidation();
controller.setRegistrationValidation(registrationValidation);
}
Not sure if its relevant, but here's my dispathcer-servlet.xml file ...
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- Enable annotation driven controllers, validation etc... -->
<mvc:annotation-driven />
<context:component-scan base-package="com.myco.eventmaven" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/messages" />
</bean>
</beans>
Here is my controller. The "usersDao" field is null during my test, causing NullPointerExceptions (works fine when I run it as a normal webapp in JBoss) ...
#Controller
#RequestMapping("/registrationform.jsp")
public class RegistrationController {
private static Logger LOG = Logger.getLogger(RegistrationController.class);
#Autowired
private RegistrationValidation registrationValidation;
#Autowired
private UsersDao usersDao;
public void setRegistrationValidation(
RegistrationValidation registrationValidation) {
this.registrationValidation = registrationValidation;
}
// Display the form on the get request
#RequestMapping(method = RequestMethod.GET)
public String showRegistration(Map model) {
LOG.debug("called GET method.");
final Registration registration = new Registration();
model.put("registration", registration);
return "user/registrationform";
}
// Process the form.
#RequestMapping(method = RequestMethod.POST)
public String processRegistration(Registration registration, BindingResult result) throws NoSuchAlgorithmException, UnsupportedEncodingException {
String nextPage = "user/registrationform";
// set custom Validation by user
registrationValidation.validate(registration, result);
if (result.hasErrors()) {
return nextPage;
} else {
// Save the user to the database.
if (usersDao.saveUser(registration)) {
nextPage = "user/registrationsuccess";
} // if
} // if
return nextPage;
}
The class of the member field, usersDao, is annotated with the #Component annotation ...
#Component("usersDao")
public class UsersDaoImpl implements UsersDao {
What additional configuration do I need to add to properly autowire the dao object in my JUnit class? Thanks, -
You're getting the null because you're instantiating RegistrationController yourself, instead of getting the bean from Spring. You almost figured that out for yourself:
// I could get the controller from the context here
controller = new RegistrationController();
You could, and you should. Remove those two lines, and use the following on the field declartion:
#Autowired
private RegistrationController controller;