I'm having trouble configuring spring-data-ldap in a web app.
I summarize what I have done:
I created a maven (called ldap-model) project, with the spring-data-ldap dependency, I created the User.java (Entry) class and the corresponding Repository: UserRepository.
Then I created a new spring mvc web project, with the liberation dependency created before (ldap-model).
I wanted to use the xml configuration, so:
root-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:ldap="http://www.springframework.org/schema/ldap"
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/ldap http://www.springframework.org/schema/ldap/spring-ldap.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<context:property-placeholder location="classpath:ldap.properties" />
<context:annotation-config />
<ldap:context-source id="contextSource"
password="${ldap.contextSource.password}" url="${ldap.contextSource.url}"
username="${ldap.contextSource.userDn}" base="${ldap.contextSource.base}"></ldap:context-source>
<ldap:repositories base-package="eu.test.ldap.repository">
</ldap:repositories>
<ldap:ldap-template id="ldapTemplate"
context-source-ref="contextSource"></ldap:ldap-template>
<bean class="eu.test.webapp.UserService">
</bean>
Here I have the first problem with tag ldap:repositories , with Ctrl + Space it's suggested to me, but it does not compile giving this error :
Multiple annotations found at this line:
- Configuration problem: Cannot locate BeanDefinitionParser for element [repositories] Offending resource: file [C:/Progetti/
Workspace di test/ldap-webapp/src/main/webapp/WEB-INF/spring/root-context.xml]
- Cannot locate BeanDefinitionParser for element [repositories]
Following the rest of the code :
UserService.java
public class UserService implements BaseLdapNameAware {
private final UserRepository userRepo;
private LdapName baseLdapPath;
#Autowired
public UserService(UserRepository userRepo) {
this.userRepo = userRepo;
}
public void find()
{
User u = userRepo.findByUid("test.test");
System.out.println(u.getUid());
}
#Override
public void setBaseLdapPath(LdapName baseLdapPath) {
this.baseLdapPath = baseLdapPath;
}}
ldap.properties
ldap.contextSource.url=*********
ldap.contextSource.userDn=cn=*********
ldap.contextSource.password=*********
ldap.contextSource.base=*********
servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="eu.test.webapp" />
HomeController.java
#Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
#Autowired
private UserService userService;
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
userService.find();
return "home";
}
}
Is there something wrong besides the error given?
I also tried to create a java configuration, not xml
I created a new spring mvc web project, with the liberation dependency created before (ldap-model).
#Configuration
#PropertySource("classpath:ldap.properties")
#ComponentScan(basePackages = {"eu.test.*"})
#Profile("default")
#EnableLdapRepositories(basePackages = "eu.test.ldap.repository.**")
public class AppConfig {
#Autowired
private Environment env;
#Bean
public LdapContextSource contextSource() {
LdapContextSource contextSource = new LdapContextSource();
contextSource.setUrl(env.getRequiredProperty("ldap.contextSource.url"));
contextSource.setBase(env.getRequiredProperty("ldap.contextSource.base"));
contextSource.setUserDn(env.getRequiredProperty("ldap.contextSource.userDn"));
contextSource.setPassword(env.getRequiredProperty("ldap.contextSource.password"));
return contextSource;
}
#Bean
public LdapTemplate ldapTemplate() {
return new LdapTemplate(contextSource());
}
}
ldap.properties like above
UserService.java
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
public String getUsernameByUid(String uid)
{
return userRepository.findByUid(uid).getUsername();
}
}
HomeController.java
#Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
#Autowired
private UserService userService;
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
String username = userService.getUsernameByUid("nome.cognome");
return "home";
}
}
I'm sure something is missing, userService is null
Does anyone have an example web project with these features?
Sorry for the english, thank you.
there seems to be a difference in parsing xml configuration since spring-ldap-core 2.3.
If you take a look at LdapNamespaceHandler class, you can see that no handler is defined for tag "repositories".
It sounds strange because there is no equivalent change in spring-ldap.xsd.
Anyway, if you want to use xml configuration approach, you can solve using spring-ldap-core 2.2 instead of spring-ldap-core 2.3, simply modifying your pom.xml.
Ciao.
Related
I have faced a real proglem and solved it, but couldn't figure out what has been happened.
I defined transactionManager and sessionFactory bean in root context and my dao class with #Transactional methods in dispatcher context. And that's all. When I was trying to use getCurrentSession() in dao, I was getting "could not obtain a current session".
But, as I can remember, dispatcher context is aware about root context and has access to all beans in root context.
Can somebody explain me, why do not transactions open before #Transactional method if transactionManager and sessionFactory were defined in root context and class with #Transactional in child context?
Database config class
#Configuration
#EnableTransactionManagement
public class DatabaseConfig {
#Bean
public LocalSessionFactoryBean sessionFactory() throws IOException {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(getDatabaseDataSource());
sessionFactoryBean.setPackagesToScan("com.varguss.domain");
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL57Dialect");
properties.setProperty("hibernate.show_sql", "true");
properties.setProperty("hibernate.hbm2ddl.auto", "update");
properties.setProperty("hibernate.connection.useUnicode", "true");
properties.setProperty("hibernate.connection.characterEncoding", "utf8");
properties.setProperty("hibernate.connection.charSet", "utf8");
sessionFactoryBean.setHibernateProperties(properties);
return sessionFactoryBean;
}
#Bean
#Autowired
public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
return new HibernateTransactionManager(sessionFactory);
}
#Bean(name = "dataSource", destroyMethod = "close")
public BasicDataSource getDatabaseDataSource() throws IOException {
BasicDataSource databaseDataSource = new BasicDataSource();
Properties properties = new Properties();
ClassPathResource propertiesFileResource = new ClassPathResource("database.properties");
properties.load(propertiesFileResource.getInputStream());
databaseDataSource.setDriverClassName(properties.getProperty("driverClassName"));
databaseDataSource.setUrl(properties.getProperty("url"));
databaseDataSource.setUsername(properties.getProperty("username"));
databaseDataSource.setPassword(properties.getProperty("password"));
return databaseDataSource;
}
}
DAO class
#Repository
#Transactional
public class DbComputerPartDAO implements ComputerPartDAO {
private SessionFactory sessionFactory;
private Strategy strategy;
#Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
strategy = StrategyFactory.getStrategy(StrategyType.ALL, sessionFactory);
}
#Override
#Transactional(readOnly = true)
public List<ComputerPart> allParts() {
return sessionFactory.getCurrentSession().createQuery("FROM ComputerPart part ORDER BY part.count DESC", ComputerPart.class).getResultList();
}
#Override
#Transactional(readOnly = true)
public ComputerPart part(Long id) {
return sessionFactory.getCurrentSession().find(ComputerPart.class, id);
}
#Override
public void save(String name, boolean isImportant, Long count) {
sessionFactory.getCurrentSession().saveOrUpdate(new ComputerPart(name, isImportant, count));
}
#Override
public void remove(Long id) {
ComputerPart computerPart = part(id);
if (computerPart != null)
sessionFactory.getCurrentSession().delete(computerPart);
}
#Override
#Transactional(readOnly = true)
public List<ComputerPart> byImportance(boolean isImportant) {
return sessionFactory.getCurrentSession().createQuery("FROM ComputerPart part WHERE part.isImportant ORDER BY part.count DESC", ComputerPart.class).getResultList();
}
#Override
public void updateImportance(Long id, boolean isImportant) {
ComputerPart computerPart = part(id);
if (computerPart != null)
computerPart.setImportant(isImportant);
}
#Override
public void updateName(Long id, String name) {
ComputerPart computerPart = part(id);
if (computerPart != null)
computerPart.setName(name);
}
#Override
public void updateCount(Long id, Long count) {
ComputerPart computerPart = part(id);
if (computerPart != null)
computerPart.setCount(count);
}
#Override
#Transactional(readOnly = true)
public List<ComputerPart> page(int pageNumber) {
return strategy.page(pageNumber);
}
#Override
#Transactional(readOnly = true)
public List<ComputerPart> parts() {
return strategy.parts();
}
#Override
#Transactional(readOnly = true)
public Integer lastPageNumber() {
return strategy.lastPageNumber();
}
#Override
#Transactional(readOnly = true)
public List<ComputerPart> search(String partOfName) {
return strategy.search(partOfName);
}
#Override
public void changeStrategy(StrategyType strategyType) {
this.strategy = StrategyFactory.getStrategy(strategyType, sessionFactory);
}
}
Root context
<?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-3.0.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">
<!-- Root Context: defines shared resources visible to all other web components -->
<context:annotation-config/>
<bean class="com.varguss.config.DatabaseConfig"/>
</beans>
Child context
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-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/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /resources/views/ directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/views/" p:suffix=".jsp" />
<context:component-scan base-package="com.varguss.dao" />
<context:component-scan base-package="com.varguss.controller" />
</beans:beans>
When using hierarchical application context (a parent and child) the child can see the beans from the parent. So it can detect the EntityManagerFactory and the PlatformTransactionManager.
However when using things like AOP that only applies to beans in the same application context as the AOP is defined in. So AOP defined in the parent context only applies to beans in the parent context, not to beans in the child contexts.
So in your case the #EnableTransactionManagement is in the parent context but in there there aren't any beans with #Transactional, those are in the child context. So either create an #Configuration which enables transactions there or use <tx:annotation-driven /> in your XML configuration.
I am new to spring. So I couldn't figure out what issue is there in the below code. I have two classes. I am defining a #Bean Channel and am autowiring that bean in the next class. I am using annotation for autowiring. When I try " System.out.println(externalChannel.toString());" am getting null values and the exception null pointer exception is thrown.
#Configuration
public class MessagingConfig
{
#Value("${service.name}")
private String queueName; // NOSONAR
#Value("${${user}")
private String schema;
#Value("${Owner}")
private String owner;
#Bean
public Channel externalChannel()
{
EventsProvider eventsProvider = new EventsProvider();
eventsProvider.setOwner(owner);
System.out.println("-------Cost And Events Channel-------"+eventsProvider.getEventsChannel());
return eventsProvider.getEventsChannel();
}
}
And Another class is
#Component
#LoggedService
#Monitored(useActualType = true)
public class MessagePublish {
#Autowired
private MessagingService messageService;
#Autowired
private Channel externalChannel;
public void publishTPSMessage(SourceTransaction sourceTransaction)
{
TPSEvent event = new TPSEvent(ContextHolder.getContextId(), new Date(), GuidUtils.generateGuid(),sourceTransaction);
Message<TPSEvent> message = new Message<TPSEvent>(event);
message.getHeader().setMessageType(TPSEvent.class.getName());
message.getHeader().setPayloadEncodingType(SystemCodecs.XML.name());
System.out.println(message.toString());
System.out.println(externalChannel.toString());
messageService.publish(externalChannel, message);
}
}
More Info
public Channel getEventsChannel() {
return Channel.builder()
.setName("necessarySources")
.setConnectionName("defaultConnection")
.setType(ChannelType.Topic)
.setConnectionData(AqSqlConnectionData.buildString(this.owner, "Safi"))
.setSubscriberNames(new String[]{"Safi_Autowire"})
.build();
}
Main Class
public class TPSHandler {
public static void main(String[] args) {
BatchExport batchExportBean=getBatchExportASJAXBElement();
System.out.println(" batchExportBean Trans Description : " + batchExportBean.getDueDate());
for(Pay pay :batchExportBean.getPay()) {
SourceTransaction sourceTransaction=mapPayBatchToSourceTransaction(pay,batchExportBean);
String sourceTraString = getSourceTransactionASXML(sourceTransaction);
System.out.println(" sourceTraString : \n" + sourceTraString);
MessagePublish messagePublish= new MessagePublish();
//SourceTransaction sourceTransaction= new SourceTransaction();
messagePublish.publishTPSMessage(sourceTransaction);
}
}
}
My Servlet.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:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:p="http://www.springframework.org/schema/p"
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://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">
<import resource="classpath:config-properties.xml" />
<import resource="classpath:datasource.xml" />
<import resource="classpath:transaction-manager.xml" />
<import resource="classpath:jmx.xml" />
<context:component-scan base-package="com.imosAdapter" />
<bean class="com.oasis.services.messaging.config.MessagingServicesConfig" />
<bean class="com.oasis.services.messaging.config.DefaultMessagingConnectorsConfig" />
<bean class="com.oasis.services.messaging.config.LoaderConfig" />
<context:annotation-config />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>/config/oasis-component.properties</value>
</property>
</bean>
</beans>
The exception thrown:
Exception in thread "main" java.lang.NullPointerException
at com.imosAdapter.tps.events.MessagePublish.publishTPSMessage(MessagePublish.java:46)
at com.imosAdapter.tps.TPSHandler.main(TPSHandler.java:64)
What is the issue over here? Can anybody help me with this? what exactly I am missing here?
You need to initialize a Spring context at the start of your application when you do not create a servlet / run as a Server.
See Using Spring in a standalone application
I am at my wits end trying to debug this issue. Basically, I have a mvc application where I have a BusinessManagerImpl class which has 2 DAOs (UserDao and ProductDao) and am using JDBC with a connection pool instead of an ORM. Database is mySQL with InnoDb engine. RestUserController is the calling class of BusinessManagerImpl.
BusinessManagerImpl.addUser() has been annotated with #Transactional annotation. I have also tried annotating #Transactional at the class level but doesn't seem to make a difference. Both DAOs are also annotated as such.
BusinessManagerImpl.addUser() uses UserDao to insert a user but a subsequent call to ProductDao.getAllProducts() throws a RuntimeException on purpose to cause the transaction to rollback. My expectation is that the user should not have been inserted as a RuntimeException has occurred and the transaction would have been rolledback but I have checked my database and the new user is inserted.
I have tried with throwing a checked exception and using the "rollback for" parameter of #Transactional annotation but it doesn't work. I have also tried different values of propagation like Propagation.Required but doesn't seem to have an effect on rolling back the transaction. I have tried searching on stackoverflow and google but came up with nothing that could help. Can someone please shed some light on what I am doing wrong or missing something? Thank you. Below is my setup:
application-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
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/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<context:component-scan base-package="someproject" />
<!-- <context:annotation-config /> -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/somedb" />
<property name="username" value="xxx" />
<property name="password" value="yyy" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
BusinessManagerImpl class
#Service
public class BusinessManagerImpl implements BusinessManager{
#Autowired
private UserDao userDao;
#Autowired
private ProductDao productDao;
....
#Override
#Transactional(propagation=Propagation.REQUIRED)
public User addUser(User user) throws Exception {
// TODO Auto-generated method stub
User tempUser = userDao.addUser(user);
productDao.getAllProducts();
return tempUser;
}
UserDaoImpl class
#Service
public class UserDaoImpl implements UserDao {
private DataSource dataSource;
#Autowired
public UserDaoImpl(DataSource dataSource) {
super();
setDataSource(dataSource);
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
private JdbcTemplate getJdbcTemplate(){
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
return jdbcTemplate;
}
...
#Override
#Transactional(propagation=Propagation.MANDATORY)
public User addUser(final User user) {
KeyHolder holder = new GeneratedKeyHolder();
final String sql = "insert into user (username, password) "
+ " VALUES (?, ?)";
getJdbcTemplate().update(new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement(sql.toString(), Statement.RETURN_GENERATED_KEYS);
int index = 1;
ps.setString(index++, user.getUsername());
ps.setString(index++, user.getPassword());
return ps;
}
}, holder);
int seq = holder.getKey().intValue();
user.setSeq(seq);
return user;
}
ProductDaoImpl class
#Service
public class ProductDaoImpl implements ProductDao {
private DataSource dataSource;
#Autowired
public ProductDaoImpl(DataSource dataSource) {
super();
setDataSource(dataSource);
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
#Override
#Transactional(propagation=Propagation.MANDATORY)
public List<Product> getAllProducts() throws Exception {
if(true)
throw new RuntimeException("on purpose");
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
List<Product> products = jdbcTemplate.query(
"select * from product",
new ProductRowMapper());
return products;
}
RestUserController class
#RestController
public class RestUserController {
private static Logger logger = LoggerFactory.getLogger(RestUserController.class);
#Autowired
private BusinessManager businessManager;
#RequestMapping(value = "/adduser", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> createEmployee(#RequestBody User user)
{
logger.debug("adding user:"+user);
User addedUser=null;
try {
addedUser = businessManager.addUser(user);
return new ResponseEntity(addedUser, HttpStatus.CREATED);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>Spring3 MVC Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application-context.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>spring-web</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-web</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
spring-web-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.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">
<context:component-scan base-package="someproject" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:annotation-driven />
</beans>
I find use of #Service annotation on Dao Implementation class weird. Try replacing them with #Repository and adding rollbackFor = {Exception.class} to all of your transactional annotations.
For your 2 application contexts configs, you have to specify the base-package differently. Do not let the web application context scan DAO package.
I have configured my spring project to cater to static resources using below settings in XML file:
<annotation-driven />
<resources mapping="/resources/**" location="/resources/" />
But when I try to access the static content directly, say using below URL:
http://localhost:8080/main/resources/css/app.css
Instead of showing up the static CSS content in the browser, the request is going to the following method in Controller:
#RequestMapping(value = "/{countryID}/{stateId}/{cityId}", method = RequestMethod.GET)
public String city(#PathVariable("countryID") String countryID, #PathVariable("stateId") String stateId, #PathVariable("cityId") String cityId, Locale locale, Model model) {
System.out.println("input "+stateId);
System.out.println("input "+countryID);
System.out.println("input "+cityId);
model.addAttribute("serverTime", "");
return "home";
}
Once the request leads to this method instead of showing up the staic CSS file, I see the JSP page returned by return call "home".
I have checked and rechecked but dont really sight any issue with set up.
Please have a look and let me what might be going wrong here.
Below is the Main Controller that my application is using.
import java.util.Locale;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
#RequestMapping("/")
public class MainController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String country(Locale locale, Model model) {
System.out.println("nothing but home page");
return "home";
}
#RequestMapping(value = "/{countryID}", method = RequestMethod.GET)
public String country(#PathVariable("countryID") String countryID, Locale locale, Model model) {
System.out.println("input country "+countryID);
return "home";
}
#RequestMapping(value = "/{countryID}/{stateId}", method = RequestMethod.GET)
public String state(#PathVariable("countryID") String countryID, #PathVariable("stateId") String stateId, Locale locale, Model model) {
System.out.println("input "+stateId);
System.out.println("input "+countryID);
model.addAttribute("serverTime", "");
return "home";
}
#RequestMapping(value = "/{countryID}/{stateId}/{cityId}", method = RequestMethod.GET)
public String city(#PathVariable("countryID") String countryID, #PathVariable("stateId") String stateId, #PathVariable("cityId") String cityId, Locale locale, Model model) {
System.out.println("input "+stateId);
System.out.println("input "+countryID);
System.out.println("input "+cityId);
model.addAttribute("serverTime", "");
return "home";
}
#RequestMapping(value = "/{countryID}/{stateId}/{cityId}/{destId}", method = RequestMethod.GET)
public String dest(#PathVariable("countryID") String countryID, #PathVariable("stateId") String stateId, #PathVariable("cityId") String cityId, #PathVariable("destId") String destId, Locale locale, Model model) {
System.out.println("input "+stateId);
System.out.println("input "+countryID);
System.out.println("input "+cityId);
System.out.println("input "+destId);
model.addAttribute("serverTime", "");
return "home";
}
}
And below is the application XML file :
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- <beans:bean class="org.springframework.web.servlet.view.tiles3.TilesViewResolver" />
<beans:bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<beans:property name="definitions">
<beans:list>
<beans:value>/WEB-INF/views.xml</beans:value>
</beans:list>
</beans:property>
</beans:bean> -->
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.travel.main" />
</beans:beans>
The problem is, your #RequestMapping in the controler has precedence over the resource-mapping. To change this, you have to do two things:
Add the attribute order="0" to your resources-tag.
Change the order of your tags to:
<resources mapping="/resources/**" location="/resources/" order="0" />
<annotation-driven />
Then it should work.
It seems http://localhost:8080/main/resources/css/app.css is mapped to /{countryID}/{stateId}/{cityId}:
countryId=resources
stateId=css
cityId=app.css
It seems the resources are only mapped when there is no Controller that matches the URL, so you can try to add to that controller a different path: You can change #RequestMapping("/") to #RequestMapping("/mainController") or add something like /city/ in the matcher of the city method: city/{countryID}/{stateId}/{cityId}.
Give a try the following options:
Remove #RequestMapping("/") from the MainController.
Add a View Resolver to your Spring configuration. For instance, InternalResourceViewResolver.
Take a look at the Spring doc.
Move the resources directory to the same level as views. That is,/WEB-INF/views and /WEB-INF/resources.
I hope that helps!
I'm having trouble doing a Spring (using 3.0.5.RELEASE) mapping. I want to map the URL http://mydomain/context-path/user/registrationform.jsp to my JSP page at
/WEB-INF/views/user/registrationform.jsp
but I'm getting a 404. I have my controller setup like so …
#Controller
#RequestMapping("registrationform.jsp")
public class RegistrationController {
private static Logger LOG = Logger.getLogger(RegistrationController.class);
…
public void setRegistrationValidation(
RegistrationValidation registrationValidation) {
this.registrationValidation = registrationValidation;
}
// Display the form on the get request
#RequestMapping(method = RequestMethod.GET)
public String showRegistration(Map model) {
final Registration registration = new Registration();
model.put("registration", registration);
return "user/registrationform";
}
here is my dispatcher-servlet.xml …
<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.burrobuie.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>
and here is my web.xml …
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
What else do I need to configure (or configure differently) to make this mapping work? This is harder than - Dave
#Controller
#RequestMapping("registrationform.jsp")
public class RegistrationController {
The RequestMapping annotation at class level should be use for a common url pattern like "item/*" and all the links that contains "/item" followed by other pattern would be mapped it to the controller. "user/" in your case
The RequestMapping annotation at method level is used for mapping the sub URL like "item/add" or "item/delete", "registrationform.jsp' in your case
So try this:
#Controller
#RequestMapping("/user")
public class RegistrationController {
private static Logger LOG = Logger.getLogger(RegistrationController.class);
…
public void setRegistrationValidation(
RegistrationValidation registrationValidation) {
this.registrationValidation = registrationValidation;
}
// Display the form on the get request
#RequestMapping(value="/registrationform.jsp",method = RequestMethod.GET)
public String showRegistration(Map model) {
final Registration registration = new Registration();
model.put("registration", registration);
return "user/registrationform";
}
This will map /user/registrationform.jsp
Change the RequestMapping to:
#RequestMapping("/user/registrationform.jsp")