Showing posts with label spring MVC. Show all posts
Showing posts with label spring MVC. Show all posts

Thursday, February 4, 2016

Caused By: org.springframework.beans.factory.BeanCreationException: Could not autowire field:

Getting following exception bringing up a Spring Application while trying to instantiate a Spring bean. I have defined the bean and autowired it in my spring controller:

Here is my service. Spring should be instantiated when I bring up the application.

@Service("nameFinderService")
@Lazy(true)
public class NameFinderServiceImpl implements INameFinderService {

}

Here is my Controller where I have autowired the above service:

@Controller
public class MainController{

@Autowired
private INameFinderService nameFinderService;

}

Full Stacktrace:

Caused By: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.nmservice.web.service.INameFinderService com.nmservice.web.base.controller.MainController.nameFinderService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.nmservice.web.service.INameFinderService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:624)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:672)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:543)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:241)



Fix : The package specified in component-scan in spring configuration was specified to a more specific package as I had my spring files in that package, The new spring bean existed one level higher in package. That was the reason it could not find the bean.

I change the following one level up,

from this
<context:component-scan base-package="com.nmservice.web.base" />
to 
<context:component-scan base-package="com.nmservice.web" />

And the issue got resolved.

Tuesday, December 1, 2015

aws mysql connection issues

I just set up a new spring mvc + hibernate application on aws instance via elastic beanstalk.
I created a new MySql db and was able to access it through my localhost, but I couldn't connect to mysql through my beanstalk application deployed on aws instance. 

I was able to fix these issues, and thought its worth sharing the solution as many others developers might be facing the same issue.  The connectivity issue could happen for different reasons, but in my 
case it was security groups that caused the issue.

First thing to make sure you correctly created you db instance, try to ping it from console.

>>>  nc -zv test.xxxxxxxxx.us-west-2.rds.amazonaws.com 3306
Connection to mgdb.czivgxrqpb9q.us-west-2.rds.amazonaws.com port 3306 [tcp/mysql] succeeded!

The aws troubleshooting guide is helpful and I would recommend to read it first.
http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Troubleshooting.html#CHAP_Troubleshooting.Connecting

Here is my spring-hibernate configuration file just for the reference:

<?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-2.0.xsd">

<bean id="appDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://xxxxxxx.us-west1.rds.amazonaws.com:3306/mgdb?zeroDateTimeBehavior=convertToNull"/>
    <property name="username" value="xxxxxx"/>
    <property name="password" value="xxxxxx"/>
</bean>

<bean id="appSessionFactory" 
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="appDataSource"/>
    <property name="mappingResources">
        <list>
            <value>employee.hbm.xml</value>        
        </list>
    </property>
    <property name="hibernateProperties">
        <value>hibernate.dialect=org.hibernate.dialect.HSQLDialect</value>
    </property>
</bean>

<bean id="hibernateTemplate" 
class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory">
        <ref bean="appSessionFactory"/>
    </property>
</bean>

</beans>

  • First Connectivity issue:

28-Nov-2015 23:58:47.504 ERROR [localhost-startStop-1] <unknown>.<unknown> Unable obtain JDBC Connection
 com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Caused by: java.net.ConnectException: Connection refused

Fix:

Initially I was getting Connection refused exception but this was gone once I updated the security group to enable all traffic to my ElasticBeanstalk application. 

I have updated the security group to accept All traffic with default IP as shown here. 
(This is okay for testing if you are troubleshooting the connectivity issue, but its a good idea to set specific protocols and destination for more security)


  • Second Connectivity issue :

org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Caused by: java.net.ConnectException: Connection timed out

Fix :
After resolving first issue I was still getting Connection timed out error. Going further in aws documentation I found that we also need to enable the DB Security group to make it accessible from EC2. 

As per aws docs - A DB security group controls network access to a DB instance that is not inside a VPC. By default, network access is turned off to a DB instance. You can specify rules in a security group that allows access from an IP address range, port, or EC2 security group. 

More can be found at this link:
http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithSecurityGroups.html

To change this, go to you DB instance and select "See Details" from "Instance Actions" dropdown.
On the details page click on the security group for your db instance.

Check the inbound and outbound settings for your DB security group. For testing purpose I am setting it to accept All traffic but its always recommended to configure more specific protocols and ip addresses, specially if its production database.

Inbound:


Outbound:





Tuesday, October 20, 2015

No converter found for return value of type: class java.util.ArrayList

I am testing a Spring MVC application , I am calling a database service which returns an ArrayList. I want to return this ArrayList as a Json response to my Jsp, where I am going to iterate through it and render search results through jquery.

 @RequestMapping(value = "/web/getprofiles", method = RequestMethod.GET)
    public @ResponseBody
    List getProfiles(HttpServletRequest request) {
        ArrayList<SearchDO> searchResults = profileService.getProfileSearch();
     return searchResults;

    }

Getting following exception while returning the ArrayList from Controller method :

Oct 20, 2015 10:45:20 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/web] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: No converter found for return value of type: class java.util.ArrayList] with root cause
java.lang.IllegalArgumentException: No converter found for return value of type: class java.util.ArrayList
at org.springframework.util.Assert.isTrue(Assert.java:68)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:124)

I am running this application on tomcat 7.0 with jdk 1.8 and Spring version 4.2.1.RELEASE.

Fix:

The exception here indicates that spring can not find a suitable converter to return ArrayList as a Json object as expected. To resolve this configure the resource resolver in your spring configuration xml.
Make you have specified <annotation-driven /> in spring configuration.



Spring configuration 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/" />

<context:component-scan base-package="com.testweb.controllers" />

<beans:bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <beans:property name="useNotAcceptableStatusCode"
        value="false" />
    <beans:property name="contentNegotiationManager">
        <beans:bean
            class="org.springframework.web.accept.ContentNegotiationManager">
            <beans:constructor-arg>
                <beans:bean
                    class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
                    <beans:constructor-arg>
                        <beans:map>
                            <beans:entry key="html" value="text/html" />
                            <beans:entry key="json" value="application/json" />
                        </beans:map>
                    </beans:constructor-arg>
                </beans:bean>
            </beans:constructor-arg>
        </beans:bean>
    </beans:property>

    <beans:property name="viewResolvers">
        <beans:list>
            <beans:bean
                class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
            
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean id="jspView"
                class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <beans:property name="prefix" value="/WEB-INF/views/" />
                <beans:property name="suffix" value=".jsp" />
            </beans:bean>
        </beans:list>
    </beans:property>

    <beans:property name="defaultViews">
        <beans:list>
            <beans:bean
                class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
        </beans:list>
    </beans:property>
</beans:bean>

</beans:beans>


             



Make sure you have added required jackson dependencies in your pom.xml

<!-- Jackson JSON Mapper -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.2</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.5.2</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.5.2</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.5.2</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.5.2</version>

</dependency>

Tuesday, August 11, 2015

A sample project using Spring MVC, Jquery and JQGrid to display the list of Object returned as a JSON object:

Following is a sample project using Spring MVC, Jquery and JQGrid to display the list of Employees returned as a JSON object:

The jsp in screenshot shows the list of employees.

I assume the user already knows how spring MVC works, so I am not explaining how Spring MVC works in this post.

You can download this sample maven project from github. 
https://github.com/SanjayIngole/jqgrid-example-parent

Here is an overview:
1. Jquery makes an Ajax call in Spring Controller method to get the ArrayList of objects (Employees).


 $.when($.getJSON('/jqgridexample/views/web/getemployees')).then(function (data) {

.....
 Rest of the code
....

));

2. In Spring Controller we map a method getEmployees to url '/web/getemployees' called from jquery. 
This method returns the ArrayList of Employees. Spring MVC takes care of converting this to a JSON Object.

@RequestMapping(value = "/web/getemployees", method = RequestMethod.GET)
public @ResponseBody
ArrayList<Employee> getEmployees(HttpServletRequest request) {


final ArrayList<Employee> employees = getMockEmployees();

return employees;
}

3. Jquery receives a list of employees as a JSON object.

[{"empID":100,"firstName":"John","lastName":"Oliver","address":"123 Hollywood Blvd, LA","phone":"4572312222"},{"empID":101,"firstName":"Barack","lastName":"Obama","address":"001 White House, DC","phone":"1010100101"},{"empID":102,"firstName":"Tom","lastName":"Cruise","address":"333 Sunset Blvd, LA","phone":"8272828222"},{"empID":103,"firstName":"Ed","lastName":"Sheeran","address":"6377 Kings Drive, London","phone":"9298292222"}]

4. This list is used to populate the jqgrid. In this case we are mapping individual fields before passing to jqgrid.

$("#employees").jqGrid({
   datatype: "local",
   height: 250,
   width: 700,
   colNames: ['EMPLOYEE ID', 'FIRST NAME', 'LAST NAME', 'ADDRESS', 'PHONE'],
   colModel: [{
       name: 'empID',
       index: 'empID',
       width: 10,
       sorttype: "int"},
   {
       name: 'firstName',
       index: 'firstName',
       width: 50},
   {
       name: 'lastName',
       index: 'lastName',
       width: 50},
   {
       name: 'address',
       index: 'address',
       width: 100},
   {
       name: 'phone',
       index: 'phone',
       width: 10}
   ],
});

var names = ['empID', 'firstName', 'lastName', 'address', 'phone'];
var employeedata = [];

for (var i = 0; i < data.length; i++) {
   employeedata[i] = {};
   employeedata[i][names[0]] = data[i].empID;
   employeedata[i][names[1]] = data[i].firstName;
   employeedata[i][names[2]] = data[i].lastName;
   employeedata[i][names[3]] = data[i].address;
   employeedata[i][names[4]] = data[i].phone;
}

for (var i = 0; i <= employeedata.length; i++) {
   $("#employees").jqGrid('addRowData', i + 1, employeedata[i]);
}

$("#employees").jqGrid('setGridParam', {ondblClickRow: function(rowid,iRow,iCol,e){alert('double clicked');}});

});

This example can be downloaded from github. Please drop me a question if required.

https://github.com/SanjayIngole/jqgrid-example-parent