Configure DataSource from Java (without XML) - mysql

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;
}

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")

connection.createStatement in Spring-managed datasource never return

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.

Custom ObjectMapper and NamingStrategy in Spring 3 MVC

I'm using Spring MVC 3 and MappingJacksonHttpMessageConverter in order to get the json data with #ResponseBody. With the default config works ok but now i need to transform the camelCase fields to Pascal casing. For this purpose, i've developed a custom naming strategy:
UpperCaseNamingStrategy.java
public class UpperCaseNamingStrategy extends PropertyNamingStrategy {
#Override
public String nameForField(MapperConfig config, AnnotatedField field, String defaultName){
return convert(defaultName);
}
#Override
public String nameForGetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName){
return convert(defaultName);
}
#Override
public String nameForSetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName){
return convert(defaultName);
}
public String convert(String defaultName){
char[] arr= defaultName.toCharArray();
if(arr.length != 0){
if(Character.isLowerCase(arr[0])){
arr[0] = Character.toUpperCase(arr[0]);
}
}
return new StringBuilder().append(arr).toString();
}
}
I set my custom strategy to the objectMapper and i set the objectMapper in the converter. These are the beans:
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper">
<property name="propertyNamingStrategy" ref="namingStrategy"/>
</bean>
<bean id="namingStrategy" class="es.unican.meteo.util.UpperCaseNamingStrategy"></bean>
The beans are registered properly because i can see it in the log but when i request the json data the behaviour is the same and the converter method is not called. Do I need more configs?
Following changes are suggested as compared to what I did in my project:
Change mapper bean class to "com.fasterxml.jackson.databind.ObjectMapper". I am using Spring 4.3
add #JsonProperty annotation to the property of class which is being serielized/deseralized
Create default constructors in class which is being serielized/deseralized
Best of Luck!

Jackson serializationConfig

I am using Jackson JSON in a Spring 3 MVC app. To not serialize each and every single Date field, I created a custom objectmapper that uses a specific DateFormat:
#Component("jacksonObjectMapper")
public class CustomObjectMapper extends ObjectMapper
{
Logger log = Logger.getLogger(CustomObjectMapper.class);
#PostConstruct
public void afterProps()
{
log.info("PostConstruct... RUNNING");
//ISO 8601
getSerializationConfig().setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SZ"));
}
//constructors...
}
This custom ObjectMapper is injected into the JsonConverter:
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
<property name="objectMapper" ref="jacksonObjectMapper" /> <!-- defined in CustomObjectMapper -->
</bean>
There is no exception in the logs and serialization works, but it is not picking up the dateformat, it simple serializes to a timestamp. The #PostConstruct annotation works, the log statement in the method is in the logs.
Does anyone know why this fails?
You may also need to specify that you want textual Date serialization, by doing:
configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
(although I was assuming setting non-null date format might also trigger it, but maybe not)
Also, you can do configuration of mapper directly from constructor (which is safe). Not that it should change behavior, but would remove need for separate configuration method.
I've done the below which works to get around compatability with Java / PHP timestamps. Java uses milliseconds since EPOCH and PHP uses seconds so was simpler to use ISO dates.
I declare the below message adapters:
<bean id="messageAdapter"
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean id="jacksonJsonMessageConvertor"
class="my.app.MyMappingJacksonHttpMessageConverter"/>
</list>
</property>
</bean>
And MyMappingJacksonHttpMessageConverter looks like the below:
public class MyMappingJacksonHttpMessageConverter extends MappingJacksonHttpMessageConverter {
public MyMappingJacksonHttpMessageConverter(){
super();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(Feature.WRITE_DATES_AS_TIMESTAMPS, false);
setObjectMapper(objectMapper);
}
}
With the above all dates are written out in ISO format.
For Spring config application.properties
spring.jackson.serialization.fail-on-empty-beans=false