I'm getting a null pointer when I try to access and use a SimpleJdbcDaoSupport. This is how I'm working it out:
In the main class
#Override
public void start(final Stage primaryStage) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
SimpleJdbcDaoImpl dao = ctx.getBean("simpleJdbcDaoImpl", SimpleJdbcDaoImpl.class);
In some other stage controller class
public class HomeController implements Initializable {
#Autowired
private SimpleJdbcDaoImpl simpleJdbcDaoImpl;
// Initializes the controller class.
#Override
public void initialize(URL url, ResourceBundle rb) {
// Stage and the rest called
}
#FXML
public void showNewCalendarStage() throws Exception {
System.out.println(simpleJdbcDaoImpl.getCircleCount());
}
The SimpleJdbcDaoSupport class
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;
public class SimpleJdbcDaoImpl extends SimpleJdbcDaoSupport {
public int getCircleCount() {
String sql = "SELECT COUNT(*) FROM KIWI_TABLE";
return this.getJdbcTemplate().queryForInt(sql);
}
}
The spring.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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:file:C:/WAKILI/WAKILIdb"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="simpleJdbcDaoImpl" class="wakiliproject.dao.SimpleJdbcDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="configLocation">
<value>
classpath:/hibernate.cfg.xml
</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.H2Dialect</prop>
</props>
</property>
</bean>
<context:annotation-config/>
<context:component-scan base-package="wakiliproject"/>
</beans>
The error:
Caused by: java.lang.NullPointerException
at HomeController.showNewCalendarStage(HomeController.java:283)
... 42 more
I'm trying to teach myself Spring and would like to, for example, populate a Label in another Controller class (other than the main class) with text retrieved from the database.
For simplicity, in this case, lets print some text from the database to the console. What am I doing wrong with the above code? Thank you all.
In order for a Spring bean to be injected with its collaborators, it has to be managed by Spring. The HomeController is actually managed by FXML, which knows nothing about Spring annotations (#Autowired) and will ignore them. Even worse, assuming that the HomeController is under the wakiliproject package (or one of its subpackages), Spring will indeed create another instance of the HomeController that will have the #Autowired stuff injected but NOT the #FXML stuff.
Depending on how you load the controller you may be able to set the instance of the HomeController retrieved from Spring as the controller of the .fxml view. So:
Make sure Spring actually sees the HomeController (this will give you an instance of HomeController with the #Autowired stuff injected).
Load the FXML document as:
HomeController homeController = springContext.getBean(HomeController.class);
FXMLLoader fxmlLoader = new FXMLLoader(xxx.getResource("HomeController.fxml"));
fxmlLoader.setController(homeController);
try {
fxmlLoader.load();
} catch...
The above is almost pseudo-code, adapt as necessary!
If the load() is successful, the the #FXML fields of the controller will be populated too and its initialization method will be called.
Check out the VERY helpful answer to this question.
Related
I created a Spring project and I would like to create multiple queries on a single file. After googling, I found this link https://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-creating-database-queries-with-named-queries/
So, I should create the file orm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings
xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
version="2.0">
<named-query name="Todo.findByTitleIs">
<query>SELECT t FROM Todo t WHERE t.title = 'title'</query>
</named-query>
</entity-mappings>
Then, the interface TodoRepository.java
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import java.util.List;
interface TodoRepository extends Repository<Todo, Long> {
#Query(nativeQuery = true)
public List<Todo> findByTitleIs();
}
The spring.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="employeeDAO" class="com.journaldev.spring.jdbc.dao.EmployeeDAOImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="employeeDAOJDBCTemplate" class="com.journaldev.spring.jdbc.dao.EmployeeDAOJDBCTemplateImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="todoRepositoryBean" class="com.journaldev.spring.jdbc.dao.TodoRepositoryBeanImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/springdb" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
</beans>
The class SpringMain.java is:
public class SpringMain {
public static void main(String[] args)
{
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
EmployeeDAO employeeDAO = ctx.getBean("todoRepositoryBean", EmployeeDAO.class);
List<Employee> les = employeeDAO.getAll();
System.out.println("The list size is: + les.size()");
ctx.close();
}
}
I think it was useful but I found a problem: How can I use the named query Todo.findByTitleIs on main class?
The tutorials of Petri Kainulainen are really good and you should achieve your goal by reading this one:
https://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-part-eight-adding-functionality-to-a-repository/
He explaines how to implement the TodoRepository class.
To use queries defined in your repository, if you are developing a rest web app, you could use a #Controller class to handle the single functionalities (e.g. TodoController). In the controller you can autowire the repository:
#Autowired
private TodoRepository todoRepository;
and then use it in your methods:
public void doSomething() {
List<Todo> todoList = todoRepository.findByTitleIs();
}
Remember that you can autowire beans only in spring managed classes (Repository, Service, Controller, Component, Configuration ecc)
Otherwise you could get the repository directly from the ApplicationContext, but it's not recommended:
Why is Spring's ApplicationContext.getBean considered bad?
Personally i use this method only for testing purpose (to create a main test class).
Then i suggest you to write your queries directly in the repository interface, to me it's much simplier (this way you can avoid using the orm.xml file). For example:
#Repository
public interface TodoRepository extends JpaRepository<Todo, Long> {
// define your custom query
#Query("SELECT t FROM Todo t WHERE t.title = :title")
public List<Todo> findByTitleIs(#Param("title") String title);
// write here all the Todo queries
}
You can also use the query creation from method names mechanism, and write the previous query like this:
public List<Todo> findByTitle(String title);
http://docs.spring.io/spring-data/jpa/docs/1.4.3.RELEASE/reference/html/jpa.repositories.html
I am newbie in Spring and now I am trying to deal with #Value annotation. I have two classes. One has annotation:
public class RssHandler {
#Value("${theTopic}")
private String theTopic;
...
And the other one:
public class RestCallImpl implements RestCall {
#Value("${senderUrl}")
private String senderUrl;
...
My properties file is:
theTopic=mytopic
senderUrl=http://localhost:8080/
My beans xml has all things that I found here in the same issues like propertyConfigurer and beans declaration (as I understand):
<?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:int="http://www.springframework.org/schema/integration"
xmlns:feed="http://www.springframework.org/schema/integration/feed"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/feed
http://www.springframework.org/schema/integration/feed/spring-integration-feed.xsd">
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
<value>file:/Users/Projects/Java/TestNotifier/resources/application.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="ignoreResourceNotFound" value="true"/>
</bean>
<!-- RSS Stuff -->
<int:channel id="inputRssFeedChannel"/>
<feed:inbound-channel-adapter id="news"
channel="inputRssFeedChannel"
url="http://feeds.feedburner.com/Techcrunch">
<int:poller fixed-rate=5000 max-messages-per-poll=100/>
</feed:inbound-channel-adapter>
<int:service-activator input-channel="inputRssFeedChannel"
ref="rssPrintOutService"
method="printRss"/>
<bean id="rssPrintOutService" class="TestNotifier.RssHandler"/>
<bean id="SnsRestCall" class="TestNotifier.RestCallImpl"/>
</beans>
When I run my app I perfectly get "theTopic", but "senderUrl" is alway null. Why so? What did I miss? Thanks in advance!
Can you try #PropertySource annotation to your class as below
#Configuration
#PropertySource(value="classpath:application.properties")
public class RestCallImpl implements RestCall {
#Value("${senderUrl}")
private String senderUrl;
}
Try using the following :
public class RestCallImpl implements RestCall {
#Value("#{senderUrl}")
private String senderUrl;
...
Basically just changing the '$' to '#'.
I am new to Spring, and have a simple problem.
I have written a simple controller with a simple constructor, annotated as shown below.
#Controller
public class LoginController
{
private LoginService loginService;
#Inject
public LoginController(LoginService loginService)
{
System.out.println("LoginController constructor - initializing login service");
this.loginService = loginService;
}
When I try to access my web app in a browser, I get the following error:
No default constructor found;
When I replace the #Inject annotation with the #Autowired annotation, it works. Can anyone explain why? Everything I've read says that have identical behavior. I'm using Tomcat 6.0.43.
Also, below is my spring dispatcher servlet xml:
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:annotation-driven/>
<context:component-scan base-package="com.rockwell_collins.webquery"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
You must be missing the JavaEE Inject API from your runtime classpath. Spring will only look for #Inject if the class is found in the classpath.
You can get it from Maven here and add it to your runtime classpath (manually or through dependencies).
I'm trying to run some tests for my controller but somehow the #Autowire annotation is not working.
Here is what I'm trying to do:
#WebAppConfiguration
#ContextConfiguration("/WEB-INF/spring/app-config.xml")
public class ClientsTest {
private Client client = new Cliente();
#Test
public void test() {
BindingResult result = mock(BindingResult.class);
ClientController clientController = new ClientController();
ModelAndView model = clientController.regClient(client, result);
Assert.assertEquals("success", model.getViewName());
}
}
#Controller
public class ClientController {
#Autowired private ClientService clientService;
#RequestMapping(value="/regClient.html", method = RequestMethod.POST)
public ModelAndView regClient(#ModelAttribute("client") #Valid Client client, BindingResult result){
ModelAndView model = new ModelAndView();
if(result.hasErrors())
{
model.setViewName("error");
}
else
{
model = clientService.regClient(client);
model.setViewName("success");
}
return model;
}
}
<?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:mvc="http://www.springframework.org/schema/mvc"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- Scans the classpath of this application for #Components to deploy as beans -->
<context:component-scan base-package="com.app.app_v2.web" />
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>client</value>
</list>
</property>
</bean>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<ref bean="clientFormatter"/>
</set>
</property>
</bean>
<bean id="clientFormatter" class="com.app.app_v2.spring.ClientFormatter"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean id="clientService" class="com.app.app_v2.services.ClientService"/>
</beans>
As far as I know the clientService is null and this is why I'm getting the exception.
Because I don't know much about running test I'm asking for your help.
Your immediate problem about #Autowire not working is related to the fact that you're explicitly instantiating the clientController, and not through Spring framework. If you want the class to be a Spring bean you need to let the Spring framework manage its lifecycle, only than the dependency injection will kick-in, and all the spring beans annotated with #Autowire will be injected. Moreover, the test should be run with spring runner SpringJUnit4ClassRunner
Note that this is not necessary, cause with your test you can go two ways. More towards unit testing, by mocking your clientService e.g. via EasyMock or Mockito. Your currently posted test looks more geared towards that way. To learn how to complete your test take a look at this blog post
On the other hand, you can go for an integration test. Since version 3.2 Spring MVC offers test module which should really be the way to write integration test against Spring MVC. You can follow a great blog series backed with source code to learn how to do it.
I have the following XML configuration:
<bean id="bean1" class="Simple"/>
<bean id="bean2" class="Simple"/>
<bean id="tasks" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="bean1" />
<ref bean="bean2" />
</list>
</constructor-arg>
</bean>
<bean id="list" class="Comp">
<property name="tasks" ref="tasks"/>
</bean>
The "tasks" contains all beans of type Simple. The problem with this is that I might forget to add a Simple bean I've configured to the list.
I could do this programatically using
Map map = context.getBeansOfType(Simple.class);
and setting the list bean with the beans retrieved.
Is there any way of doing this using just XML configuration?
Your context file should like this:
<bean id="bean1" class="Simple"/>
<bean id="bean2" class="Simple"/>
<bean id="list" class="Comp" autowire="byType"/>
Note the autowire="byType" addition, and the autowiring documentation.
I would suggest writing your own FactoryBean for creating such a list. This would be reusable and then configurable using XML only. The FactoryBean would look like
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;
public class CollectingListFactoryBean implements FactoryBean, ApplicationContextAware {
private ApplicationContext appCtx;
private Class type;
public Object getObject() {
Assert.notNull(type, "type must be initialized");
List result = new ArrayList();
result.addAll(appCtx.getBeansOfType(type).values());
return result;
}
public Class getObjectType() {
return List.class;
}
public boolean isSingleton() {
return false;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.appCtx = applicationContext;
}
public void setType(Class type) {
this.type = type;
}
}
Then your XML configuration would be
<bean id="bean1" class="Simple"/>
<bean id="bean2" class="Simple"/>
<bean id="tasks" class="CollectingListFactoryBean">
<property name="type" value="Simple" />
</bean>
<bean id="list" class="Comp">
<property name="tasks" ref="tasks"/>
</bean>
NOTE: I didn't have the time to test the example above. I just used code I already had as a template. ;) Especially I'm not sure if passing Simple as a Class argument for the type property works this way. Just give it a try. In the worst case you would have to use String as the property type and use Class.forName(type) to get your class. But my guess is that Spring does this transformation for you.
EDIT Even though this solution should work, I recommend Robert Munteanu's answer.