connection.createStatement in Spring-managed datasource never return - mysql

This is very strange in my RESTful WS development. I am using Tomcat 7 with Jersey 1.8, Spring 2.5 and MySQL database.
I defined two data sources like this:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
<property name="jndiName" value="jdbc/MAINDB" />
<property name="resourceRef" value="true" />
</bean>
<bean id="orderDataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
<property name="jndiName" value="jdbc/ORDERS" />
<property name="resourceRef" value="true" />
</bean>
and inject one data source into the servlet context like this:
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="orderData">
<ref bean="orderDataSource" />
</entry>
</map>
</property>
</bean>
and this code:
orderDataSource = (DataSource) sc.getServletContext().getAttribute("orderData");
Order ord = new Order();
Statement stmt = null;
try {
stmt = orderDataSource.getConnection().createStatement();
} catch (SQLException ex) {
Logger.getLogger(OrdersResource.class.getName()).log(Level.SEVERE, null, ex);
}
gets executed 6 or 7 times flawlessly and from the 8th request, it gets stall at createStatement() line and never return or throw any exception!
However, all other resources API from MAINDB still works very well.
Anyone knows what's happening?

Why are you bothering with such code yourself? If you are using Spring already, use the JdbcTemplate instead. It can be initialized with your DataSource and will manage all that for you.
You are requiring a connection from the pool but you never closes it (same for the statement actually). Using JdbcTemplate prevents you from having those issues in the first place.
Something like
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.execute(...)
See the javadoc for more details.

Related

Hibernate Connection Leak

i'm kinda new on web dev, i'm a trainee on a company since last year and i have the following problem:
I'm making a web app with JSF2.3 and Hibernate 5.4.2.Final and c3p0 5.4.2.Final. The thing is everytime i run and go for the login page, i need to check if there is an admin user already registered - i make a count on employee's table based on employee's code - and if there isn't any administrator, then i get a list of country states and render a form register menu.
So, i get the session from the sessionfactory.opensession() in mine HibernateUtil.class, do the count and clear/close the session like the snipet:
public Long retornaLong(String query) throws Exception{
Session session = new HibernateUtil().getSession();
try {
return (Long) session.createQuery(query).getSingleResult();
}finally {
session.clear();
session.close();
}
}
then i get the country states list from
#SuppressWarnings("unchecked")
public List<T> retornaList(String query) throws Exception{
Session session = new HibernateUtil().getSession();
try {
return (List<T>) session.createQuery(query).getResultList();
}finally {
session.clear();
session.close();
}
}
but if i keep refreshing the page (#viewscoped), like 15+ times, eventually i'll get too many connection exception, this doesn't happen if i use one session for both queries. I think there's no enough time for the session to close, causing a connection leak. I want to use one session for each query, can someone help me. Thanks a lot.
My hibernate.cfg.xml
<hibernate-configuration>
<!-- a SessionFactory instance listed as /jndi/name -->
<session-factory>
<!-- properties -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/vetsnpets?useTimezone=true&serverTimezone=UTC</property>
<property name="hibernate.connection.username">vetsNpets</property>
<property name="hibernate.connection.password">123</property>
<property name="hiberante.show_sql">false</property>
<property name="hiberante.format_sql">false</property>
<property name="hbm2ddl.auto">validate</property>
<property name="current_session_context_class">thread</property>
<!-- C3P0 -->
<property name="hibernate.c3p0.initialPoolSize">3</property>
<property name="hibernate.c3p0.minPoolSize">3</property>
<property name="hibernate.c3p0.maxPoolSize">20</property>
<property name="hibernate.c3p0.maxStatements">100</property>
<property name="hibernate.c3p0.maxStatementsPerConnection">5</property>
<property name="hibernate.c3p0.maxIdleTime">2700</property>
<property name="hibernate.c3p0.maxIdleTimeExcessConnections">600</property>
<property name="hibernate.c3p0.acquireIncrement">1</property>

Export Database Table To JSon Using Apache Camel Not Behaving As Expected

I would like to export a table of a database to JSON file with this code using the code listed below, the code runs but splits returned data rows into a file per record not a single file as expected.
Camel's route :
public void configure() throws Exception {
JsonDataFormat jsonFormat = new JsonDataFormat(JsonLibrary.XStream);
jsonFormat.setUnmarshalType(Customer.class);
from("sql: SELECT * FROM assignment01.staff?dataSourceRef=dataSource")
.marshal(jsonFormat)
.to("file:data/test");
}
there is my xml
<bean id="route" class="com.huyqtran.JSonRoute"/>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="route"/>
</camelContext>
<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/assignment01?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</bean>
I expect that the application just create one JSON file for the whole table.
Tell Camel to append to the file with option fileExist=Append: http://camel.apache.org/file2, eg
.to("file:data/test?fileExist=Append");
or tell the SQL component to return the entire result-set by turning of its iterator, eg useIterator=false
from("sql: SELECT * FROM assignment01.staff?dataSourceRef=dataSource&useIterator=false")

Configure DataSource from Java (without XML)

I'm starting to develop a test application with Spring MVC and Hibernate, and I have a question about the database configuration.
I know I am able to define the datasource through the application-context.xml, like
<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/testdb"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
But I wanted not to use XML at all, so I created a configuration class in which I wanted to load a DataSource object, with a method similar to this:
#Bean
public DataSource dataSource() {
...
}
My question is: how can I get a DataSource instance that points to my MySQL schema? If there are several options, which is the best in your opinion?
I want to use a MySQL database, not an embedded one
Thanks
As I was working with Spring MVC, I solved it in the following way:
#Bean
public DriverManagerDataSource getMySQLDriverManagerDatasource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setPassword("password");
dataSource.setUrl("jdbc:mysql://localhost:3306/mytestdb");
dataSource.setUsername("root");
return dataSource;
}

Binary File To SQL Database Apache Camel

I need some guidance around which approach to use to load binary files from a folder into a MySQL Database using Camel. Basically I want to store voice logs from our PBX system into a database. The directory with the voice logs will be a remote directory
I have designed a prototype but I am not sure if this is really efficient, it works but I am not happy with the design. Let me explain what I am doing. Camel route as follows:
<camelContext xmlns="http://camel.apache.org/schema/spring">
<package>com.hia.camelone</package>
<route>
<from uri="file://c:/CTest/Inbox?noop=true&recursive=true&delay=3000"/>
<to uri="bean://fileToSQL"/>
<to uri="jdbc://timlogdb"/>
</route>
</camelContext>
<bean id="timlogdb" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value=" com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/TimLog" />
<property name="username" value="root" />
<property name="password" value="blahblah" />
</bean>
<bean id="fileToSQL" class="com.hia.camelone.fileToSQL"/>
And the code to fileToSQL bean is:
public class fileToSQL {
public String toString(#Headers Map<String,Object> header, #Body Object body){
StringBuilder sb = new StringBuilder();
String filename =(String)header.get("CamelFileNameOnly");
String escapedFileName = StringEscapeUtils.escapeJava(filename).replace("\'", "");
String filePath = StringEscapeUtils.escapeJava((String)header.get("CamelFilePath"));
sb.append("insert into FileLog ");
sb.append("(FileName,FileData) values (");
sb.append("'").append(escapedFileName).append("',").append("LOAD_FILE(\"").append(filePath).append("\")");
sb.append(")");
System.out.println(sb.toString());
System.out.println(body);
System.out.println(header.toString());
return sb.toString();
}
}
Ok short explanation I get the file component to consume the files then I build a SQL string using the MySQL LOAD_FILE() function to load the file.
My thoughts around this:
The LOAD_FILE function only works on the local machine and thus this route will only with the files being on the local machine. I could use a file producer to copy the files from some remote directory to a local directory and then use the route. My route would be something like this then:
<route>
<from uri="file://c:/CTest/Inbox?noop=true&recursive=true&delay=3000"/>
<to uri="file://c:/outbox"/>
<to uri="bean://fileToSQL"/>
<to uri="jdbc://timlogdb"/>
</route>
However since I have access to the files content in the message from the files consumer I should be able to theoretically be able to access the body/content of the string and build a SQL command that does NOT use the LOAD_FILE() function.
The only way I know how to build such a string is by using the prepared statement of JDBC. This would be first prize if I could somehow build a insert statement with the content from the file consumer.
Can I create a prepared statement in my fileToSQL bean and pass it to my jdbc component?
Or how do I build a INSERT statement without the LOAD_FILE() function?
Since I have to use the LOAD_FILE() function I would now have to cater for both unix and windows filepaths. While this should not be difficult I just dont like the idea of putting OS specific code into my applications(feels like a work around).
Anybody here ever uploaded binary files to a MySQL database using Camel who can give me some guidance on the points above. While I could work around the problems I just want to make sure I dont miss a obvious way of doing things.
I had a look around here and only found people working with mostly text files. Guys please don't even go down the route of me storing the file on the files system and linking it to the database. We have some very specific disaster recovery requirements and legal requirements that enforce the need for me to store it in a database.
Right so I managed to find a way and it was not that difficult. What I essentially did was get rid of the JDBC Camel Component in the route. I then injected the data source bean into my fileToSQL bean. I then used a simple prepared statement to insert the file and its name into MySQL.
As always code is much more explicit than my english.
<camelContext xmlns="http://camel.apache.org/schema/spring">
<package>com.hia.camelone</package>
<route>
<from uri="file://c:/CTest/Inbox?noop=true&recursive=true&delay=3000"/>
<to uri="bean://fileToSQL"/>
<!--<to uri="jdbc://timlogdb"/>-->
</route>
</camelContext>
<bean id="timlogdb" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value=" com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/TimLog" />
<property name="username" value="root" />
<property name="password" value="lalala" />
</bean>
<bean id="fileToSQL" class="com.hia.camelone.fileToSQL">
<property name="dataSource" ref="timlogdb"/>
</bean>
As you can see I inject my timlogdb bean into my fileToSQL bean. Spring ROCKS!
So here is my fileToSQL bean.
public class fileToSQL {
private DriverManagerDataSource dataSource;
private static final String SQL_INSERT="insert into FileLog(FileName,FileData)values(?,?)";
#Handler
public void toString(#Headers Map<String,Object> header,Exchange exchange){
Connection conn = null;
PreparedStatement stmt=null;
String filename =StringEscapeUtils.escapeJava(((String)header.get("CamelFileNameOnly")).replace("\'", ""));
try {
conn= dataSource.getConnection();
stmt =conn.prepareStatement(SQL_INSERT);
stmt.setString(1, filename);
byte[] filedata = exchange.getIn().getBody(byte[].class);
stmt.setBytes(2,filedata );
int s = stmt.executeUpdate();
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
finally{
try
{
if (stmt!=null)
{
stmt.close();
}
if (conn!=null)
{
conn.close();
}
}
catch(SQLException e)
{
System.out.println(e.getMessage());
}
}
}
/**
* #param dataSource the dataSource to set
*/
public void setDataSource(DriverManagerDataSource dataSource) {
this.dataSource = dataSource;
}
}
The guys from Camel did a great job. Camel is truly flexible especially when you combine it with Spring.
What a ride!

Spring MVC POST #RequestBody don't bind to JSON string in the http request

this is my signature of the POST method of my Spring MVC controller
#RequestMapping(value="/createNewGame", method=RequestMethod.POST)
public ModelAndView createNewGame(#RequestParam(value="phoneNumber") String param,#RequestBody final SampleDTO sampleDTO) {
Map model2 = new HashMap();
model2.put("firstname", "Peter");
model2.put("secondname", "Schmitt");
return new ModelAndView("jsonView", model2);
}
instead this is the definition of the SampleDTO class:
public class SampleDTO implements Serializable{
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
I'm not able to execute the request for this method. I have this error from the client:
org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.supports(Ljava/lang/Class;)Z
after execute this POST request with RestClient app with these parameters:
http://localhost:8080/SpringExample5/createNewGame.json?phoneNumber=6 (POST)
Content-Type application/json (Header attribute)
{ "value": "a" } (Body)
This is also the configuration of Spring in my web app:
<bean name="/gameController.json"
class="com.alu.server.games.acquisition.controllers.GameController"/>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
<bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
<bean id="jsonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
<property name="objectMapper">
<ref bean="JacksonObjectMapper" />
</property>
</bean>
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonHttpMessageConverter" />
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="objectMapper">
<ref bean="JacksonObjectMapper" />
</property>
</bean>
<bean id="JacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />
Someone can help me in order to find the problem?
Thanks in advance !
In the setting I used I did specify the Media Type to be "application/json" both in the web service's annotation as well as the XML configuration for json message converter.
Please checkout my FAQ on the matter here for further details.