Spring3 - #Autowired - spring-mvc

This is my applicationContext.xml
<bean id="JdbcUserDao" class="controller.User.JdbcUserDao">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="org.apache.derby.jdbc.ClientDriver"
p:url="jdbc:derby://localhost:1527/TodoDb"
p:username="root"
p:password="root" />
This is my implDao class :
#Repository
public class JdbcUserDao implements IUserDao {
private JdbcTemplate jt;
#Autowired
private DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
jt = new JdbcTemplate(this.dataSource);
}
public JdbcTemplate getJt() {
return jt;
}
public void setJt(JdbcTemplate jt) {
this.jt = jt;
}
#Override
public List<User> getUsers(final String username, final String password) {
List<User> users = this.jt.query("SELECT username, password FROM USERS",
new RowMapper<User>() {
#Override
public User mapRow(ResultSet rs, int i) throws SQLException {
User user = new User();
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
return user;
}
});
return users;
}
}
Problems:
this.dataSource available when it sets the dataSource through #Autowired like the configs in xml
when I use dataSource in getUsers, it become null ?
Questions:
How can I get this works ?
I'm new to spring3 so I really need your help.

In order to use autowiring, you need to add the following to your xml file configuration.
<context:annotation-config />
If it doesn't help then please add
<context:component-scan base-package="org.springframework.jdbc.datasource" />

Try adding the AutowiredPostProcessor to the config
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
</bean>

You could try adding the autowire to the set method instead of the property.

you need to import the class which you are doing autowired without access modifiers in repository class file
com.<your project>.controller.User.JdbcUserDao
and spring annotation
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.CrudRepository;
#Repository
public class JdbcUserDao implements IUserDao {
#Autowired
DataSource dataSource;

Related

Spring data redis error in Spring mvc framework

I'm using to redis in spring mvc based web application.
so I used spring-data-redis & jedis.
The library version is the following.
Spring MVC 4.1.6
jedis 3.0
Spring data redis 1.6 SNAPSHOT
Redis Server 3.0.2 (installed on Cent OS 7)
Application configuration is following:
-spring configuration xml(applicationContext.xml)
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxWaitMillis" value="3000"/>
<property name="maxTotal" value="50"/>
<property name="testOnBorrow" value="true"/>
</bean>
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:database="16" p:usePool="true"
p:poolConfig-ref="jedisPoolConfig" p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connectionFactory-ref="connectionFactory" />
-RedisServices.java
public interface RedisServices {
List getAppInfos();
void add_appinfo(List data);
}
-RedisServicesImpl.java
#Service
public class RedisServicesImpl implements RedisServices{
#Autowired
private RedisTemplate<String, Object> redisTemplate;
#Resource(name="redisTemplate")
private ValueOperations<String, Object> valueOps;
#Override
public List getAppInfos() {
return (List)valueOps.get(Constants.APP_INFO_KEY);
}
#Override
public void add_appinfo(List data) {
valueOps.set(Constants.APP_INFO_KEY, data);
}
}
- AppController.java
#RestController
#RequestMapping(value = "/appinfo")
public class AppsController {
#Autowired
private RedisServices redis;
#RequestMapping(value = "/mobiles",method = RequestMethod.GET)
public List view_apps_register(){
List data=new ArrayList();
List lst=services.view_app_register(apps);
for (int i = 0; i < lst.size(); i++) {
Map ap = (Map) lst.get(i);
String server=(String) ap.get("server");
if(server.equals(apps)){
data.add(ap);
}
}
redis.add_appinfo(data);
return null;
}
}
The following errors raised
java.lang.IllegalAccessError: tried to access method redis.clients.util.Pool.returnResource(Ljava/lang/Object;)V from class org.springframework.data.redis.connection.jedis.JedisConnection
at org.springframework.data.redis.connection.jedis.JedisConnection.close(JedisConnection.java:251)
at org.springframework.data.redis.connection.jedis.JedisConnection.<init>(JedisConnection.java:184)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.java:252)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.java:58)
at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:128)
at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:91)
at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:78)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:178)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:153)
at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:86)
at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:169)
at com.wwzz.services.redis.RedisServicesImpl.add_appinfo(RedisServicesImpl.java:63)
Help me!!!!

MockMVC Integrate test controller with session scoped bean

I am trying to integrate test a Spring Controller method that uses a spring session scoped bean which is injected into the controller. In order for my test to pass I must be able to access my session bean to set some values on it before I make my mock call to this controller method. Issue is a new session bean is created when I make the call instead of using the one I pulled of the mock application context. How can I make my controller use the same UserSession bean?
Here is my test case
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration("src/main/webapp")
#ContextConfiguration({"file:src/main/webapp/WEB-INF/applicationContext.xml",
"file:src/main/webapp/WEB-INF/rest-servlet.xml",
"file:src/main/webapp/WEB-INF/servlet-context.xml"})
public class RoleControllerIntegrationTest {
#Autowired
private WebApplicationContext wac;
protected MockMvc mockMvc;
protected MockHttpSession mockSession;
#BeforeClass
public static void setupClass(){
System.setProperty("runtime.environment","TEST");
System.setProperty("com.example.UseSharedLocal","true");
System.setProperty("com.example.OverridePath","src\\test\\resources\\properties");
System.setProperty("JBHSECUREDIR","C:\\ProgramData\\JBHSecure");
}
#Before
public void setup(){
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
mockSession = new MockHttpSession(wac.getServletContext(), UUID.randomUUID().toString());
mockSession.setAttribute("jbhSecurityUserId", "TESTUSER");
}
#Test
public void testSaveUserRole() throws Exception {
UserSession userSession = wac.getBean(UserSession.class);
userSession.setUserType(UserType.EMPLOYEE);
userSession.setAuthorizationLevel(3);
Role saveRole = RoleBuilder.buildDefaultRole();
Gson gson = new Gson();
String json = gson.toJson(saveRole);
MvcResult result = this.mockMvc.perform(
post("/role/save")
.contentType(MediaType.APPLICATION_JSON)
.content(json)
.session(mockSession))
.andExpect(status().isOk())
.andReturn();
MockHttpServletResponse response = result.getResponse();
}
Here is my controller method I am needing tested
#Resource(name="userSession")
private UserSession userSession;
#RequestMapping(method = RequestMethod.POST, value = "/save")
public #ResponseBody ServiceResponse<Role> saveRole(#RequestBody Role role,HttpSession session){
if(userSession.isEmployee() && userSession.getAuthorizationLevel() >= 3){
try {
RoleDTO savedRole = roleService.saveRole(role,ComFunc.getUserId(session));
CompanyDTO company = userSession.getCurrentCompany();
It is not passing this line because the UserSession Object is not the same
if(userSession.isEmployee() && userSession.getAuthorizationLevel() >= 3){
This is the declaration of my user session bean.
#Component("userSession")
#Scope(value="session",proxyMode= ScopedProxyMode.INTERFACES)
public class UserSessionImpl implements UserSession, Serializable {
private static final long serialVersionUID = 1L;
Both controlle and bean are created using component scan in my applicationContext.xml
<context:annotation-config />
<!-- Activates various annotations to be detected in bean classes -->
<context:component-scan
base-package="
com.example.app.externalusersecurity.bean,
com.example.app.externalusersecurity.service,
com.example.app.externalusersecurity.wsc"/>
<mvc:annotation-driven />
Add the following bean configuration, which adds a session context for each thread
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="session">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
An equivalent in Java's configuration class would the following bean declaration
#Bean
public CustomScopeConfigurer scopeConfigurer() {
CustomScopeConfigurer configurer = new CustomScopeConfigurer();
Map<String, Object> workflowScope = new HashMap<String, Object>();
workflowScope.put("session", new SimpleThreadScope());
configurer.setScopes(workflowScope);
return configurer;
}
For more details, see
http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/beans.html#beans-factory-scopes-custom-using
Using different Bean definition profiles for test and production worked for me - here's how a XML based setup could look like:
<beans profile="production">
<bean id="userSession" class="UserSessionImpl" scope="session" >
<aop:scoped-proxy/>
</bean>
</beans>
<beans profile="test">
<bean id="userSession" class="UserSessionImpl" >
</bean>
</beans>
To use the test profile for your test, add #ActiveProfiles to your test class:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration("src/main/webapp")
#ContextConfiguration({"file:src/main/webapp/WEB-INF/applicationContext.xml",
"file:src/main/webapp/WEB-INF/rest-servlet.xml",
"file:src/main/webapp/WEB-INF/servlet-context.xml"})
#ActiveProfiles(profiles = {"test"})
public class RoleControllerIntegrationTest {
[...]

How to set #Required field in Spring without using the application-context.xml file?

I am using Spring-Boot and I am trying to set the required properties (i.e. properties with the #Required tag) of an implemented Service without using the application-context.xml file. In my application-context.xml file the service looks like this:
<bean class="services.impl.MyServiceImpl">
<property name="property" value="value" />
</bean>
I guess that the properties looks something like this in Java:
protected Properties buildMyServiceImplProperties()
{
Properties myServiceImplProperties = new Properties();
myServiceImplProperties.setProperty("property", "value");
return myServiceImplProperties;
}
EDIT: The service class MyService is define as follows:
package services;
public interface MyService {}
And the implementation is:
package services.impl;
import services.DoctorService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service
#Transactional
public class MyServiceImpl implements MyService {
private String value;
#Required
public void setProperty(String value) {
this.value = value;
}
}
Not sure if I understand your question, but if you're wanting to create that bean in Java Config, you only need something like this:
#Bean
public MyService(){
MyService service = new MyServiceImpl();
service.setProperty("property", "value");
return service;
}

Spring StringTrimmerEditor trim all fields except password field

In registered a StringTrimmerEditor in a Spring controller.
Of course when I now enter a password starting or ending with whitespace it is trimmed as well. But an user doesn't recognize this trimming.
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
}
So is it possible to 'exclude' the password field from trimming.
Should I register a StringTrimmerEditor for each field or just declare password as char[]?
Although this is an old question, if you still get tripped on this then here is how I solved this.
Say we have this form src/main/webapp/view/greet-form.html (I am using Thymeleaf)
<form action="/something" th:attr="action=#{/greet}" method="post" th:object="${student}">
<p><strong>Enter your first name</strong></p>
<p><input type="text" th:field="*{firstName}" th:value="*{firstName}"> <span class="error">*</span><br />
<span class="error_message" th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}"></span></p>
<p><strong>Enter your secret code</strong></p>
<p><input type="text" th:field="*{secretCode}" th:value="*{secretCode}"> <span class="error">*</span><br />
<span class="error_message" th:if="${#fields.hasErrors('secretCode')}" th:errors="*{secretCode}"></span></p>
<p><input type="submit" value="Submit"></p>
</form>
When the form is submitted, we want Spring to trim the value of firstName but leave secretCode as it is.
This is our form backing class, defined in src/main/java/Student.java. The trick is not to use String type for secretCode but some other custom type. This way, StringTrimmerEditor will not be used for the secretCode and the data will not be trimmed.
public class Student {
private String firstName;
private SecretString secretCode;
public Student() {
//
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public SecretString getSecretCode() {
return secretCode;
}
public void setSecretCode(SecretString secretCode) {
this.secretCode = secretCode;
}
}
Here is the definition of SecretString in src/main/java/SecretString.java
public class SecretString {
private String secret;
public SecretString() {
secret = "";
}
public SecretString(String secret) {
//mandatory null check
secret = (secret == null)? "" : secret;
this.secret = secret;
}
#Override
public String toString() {
return secret;
}
}
But now Spring will complain about not being able to convert String to SecretString. This can be solved with a custom property editor or a custom converter (if you are using Spring 3+). I used a custom converter like this.
First define the code in src/main/java/SecretStringConverter.java
import org.springframework.core.convert.converter.Converter;
public class SecretStringConverter implements Converter<String, SecretString> {
#Override
public SecretString convert(String source) {
return new SecretString(source);
}
}
Then register our converter class with a conversion-service factory bean (I am using src/main/webapp/WEB-INF/spring-mvc-demo-servlet.xml)
<context:component-scan base-package="your package" />
<mvc:annotation-driven conversion-service="app_conversion_service"/>
<bean id="app_conversion_service" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="SecretStringConverter"></bean>
</list>
</property>
</bean>
Set password as disallowed field
binder.setDisallowedFields("password");

How to apply JSON on Spring MVC 4.0 app by using JavaConfig?

I want to use JSON (jackson library) with my existing app by using JavaConfig (Spring MVC 4.0)
I have my configuration :
#Configuration
#EnableWebMvc
#ComponentScan({ "my.package.controller" })
public class WebConfiguration extends WebMvcConfigurerAdapter {
#Bean(name = "viewResolver")
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
I want to apply JSON configuration but I don't find a solution.
I think I must extends WebMvcConfigurerAdapter. And another detail, I use Spring Security.
Could you help me ?
Thanks
Try this one:
#Bean
public ViewResolver contentNegotiatingViewResolver(
ContentNegotiationManager manager) {
List< ViewResolver > resolvers = new ArrayList< ViewResolver >();
InternalResourceViewResolver r1 = new InternalResourceViewResolver();
r1.setPrefix("/WEB-INF/pages/");
r1.setSuffix(".jsp");
r1.setViewClass(JstlView.class);
resolvers.add(r1);
JsonViewResolver r2 = new JsonViewResolver();
resolvers.add(r2);
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setViewResolvers(resolvers);
resolver.setContentNegotiationManager(manager);
return resolver;
}
And to add Jackson support should use MappingJacksonJsonView or MappingJackson2JsonView
public class JsonViewResolver implements ViewResolver {
public View resolveViewName(String viewName, Locale locale) throws Exception {
MappingJacksonJsonView view = new MappingJacksonJsonView();
view.setPrettyPrint(true);
return view;
}
}
In application.xml just to clarify my example have this config
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
So probably need to add mediaTypes to the ContentNegotiatingViewResolver in the #Bean method.
Check this for more about the ContentNegotiation

Resources