In pom.xml, specify default ImplementationEntries and SpecificationEntries as below:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<Implementation-Version>${project.version}</Implementation-Version>
</manifestEntries>
</archive>
<archiveClasses>true</archiveClasses>
</configuration>
</plugin>
These fields will be automatically added to MANIFEST file.
In Java class, use this snippet to read value:
@Override
public BuildVersion getVersion() throws IOException {
Package p = this.getClass().getPackage();
BuildVersion buildVersion = new BuildVersion();
buildVersion.setBuildName(p.getImplementationTitle());
buildVersion.setVersion(p.getImplementationVersion());
return buildVersion;
}
(BuildVersion is a custom class that contains result.)
Note: war file has to be put in server. At that time manifest file will be available to read properly.
Monday, December 29, 2014
Thursday, December 25, 2014
Create Index and using Index hints
CREATE INDEX:
There are many types of index introduced by Oracle.http://docs.oracle.com/cd/B19306_01/server.102/b14231/indexes.htm
Each type have the different way to create. Ex:
CREATE INDEX programId_index ON PROGRAM(programId) COMPUTE STATISTICS;
Put Index on columns that appear in WHERE statement.
Good for single column - one index.
Can put multi-columns in index but make sure that the all these columns appear in WHERE statement. If not, index does not help.
Ex: CREATE INDEX User_index ON PROGRAM(firstName, lastName, title) COMPUTE STATISTICS;
Great if: SELECT * from User WHERE firstName = ? AND lastName = ?
Bad if: SELECT * from User WHERE lastName = ?
or SELECT * from User WHERE lastName = ? AND title = ?
Index will make DML (insert, update, delete) slow down (3-time slower than the table with no indexes). Should not index on column that value is too much duplicated.
INDEX HINTS:
Use Hints indicate Oracle using index:SELECT /*+ index(table_name(column_has_indexed)) */ * FROM customer;
Oracle Semi-Joins and Anti-Joins
Using EXISTS and IN.
Example 1:
SELECT D.deptno, D.dname FROM dept D, emp E WHERE E.deptno = D.deptno ORDER BY D.deptno;
Change to:
SELECT D.deptno, D.dname FROM dept D WHERE EXISTS ( SELECT 1 FROM emp E WHERE E.deptno = D.deptno ) ORDER BY D.deptno;
Example 2:
SELECT D1.deptno, D1.dname FROM dept D1 MINUS SELECT D2.deptno, D2.dname FROM dept D2, emp E2 WHERE D2.deptno = E2.deptno ORDER BY 1;
Change to:
SELECT D.deptno, D.dname FROM dept D WHERE NOT EXISTS ( SELECT 1 FROM emp E WHERE E.deptno = D.deptno ) ORDER BY D.deptno;
References:
http://www.dbspecialists.com/files/presentations/semijoins.html
Sunday, December 14, 2014
RestTemplate cannot map a single object to a list
ResponseEntity<String> response =
restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
resObject = mapper.readValue(response.getBody(),
ResponseObject.class);
The problem is that if ResponseObject in server side has only one item set to a list, by default, JAXB will convert this list to a single json object (not an array contains one object as we expected) so the mapper in client side cannot map correctly.
Solution 1: by code
List converters =
restTemplate.getMessageConverters();
for (Object converter : converters) {
if (converter instanceof MappingJacksonHttpMessageConverter) {
MappingJacksonHttpMessageConverter jconverter =
(MappingJacksonHttpMessageConverter) converter;
final ObjectMapper mapper = new ObjectMapper();
mapper.configure(
DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY,
true);
jconverter.setObjectMapper(mapper);
}
}
Solution 2: by XML configuration:
<!-- Jackson Mapper -->
<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="jacksonObjectMapper" />
<property name="targetMethod" value="configure" />
<property name="arguments">
<list>
<value type="org.codehaus.jackson.map.DeserializationConfig.Feature">FAIL_ON_UNKNOWN_PROPERTIES</value>
<value>false</value>
</list>
</property>
</bean>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</list>
</property>
</bean>
Hope that helps.
References:
http://stackoverflow.com/questions/14343477/how-do-you-globally-set-jackson-to-ignore-unknown-properties-within-spring
Friday, December 12, 2014
Jersey Test
pom.xml
<!-- Jersey --><dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId>
<artifactId>jersey-test-framework-grizzly2</artifactId>
<version>1.8</version>
<scope>test</scope>
</dependency>
Test class:
public class MyClassTest extends JerseyTest {@Override
public AppDescriptor configure() {
return new WebAppDescriptor.Builder("com.example.person.endpoint")
.servletClass(SpringServlet.class)
.contextParam("contextConfigLocation", "classpath:context/endpointIntegrationContext.xml")
.contextListenerClass(ContextLoaderListener.class)
.contextPath("test-project").build();
}
@Before
public void setUp() {
mapper.configure(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
}
@After
public void tearDown() {
}
@Test
public void testGetByUserId() throws Exception {
RestTemplate restTemplate = new RestTemplate();
Long userId = 1L;
String endpoint = getBaseURI() + "test-project/person/getByUserId/{userId}";
final Map<String, Object> urlParameter = new HashMap<String, Object>();
urlParameter.put("userId", userId);
HttpHeaders headers = new HttpHeaders();
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(endpoint, HttpMethod.GET, entity, String.class, urlParameter);
responseEntity.getBody()
//...
}
Thursday, December 11, 2014
Using Spring Data JPA
Spring Data JPA is a library / framework that adds an extra layer of abstraction on the top of our JPA provider.
DAO Structure
Configuration:
<?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:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
">
<!-- Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven />
<jpa:repositories base-package="com.journaldev.spring.repository"/>
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources
in the /WEB-INF/views directory -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<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/spring-data-jpa" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
<property name="database" value="MYSQL"/>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<!-- spring based scanning for entity classes-->
<property name="packagesToScan" value="com.journaldev.spring.model"/>
</bean>
<bean id="personDAO" class="com.journaldev.spring.dao.PersonDAOImpl">
<property name="em" ref="entityManagerFactory" />
</bean>
<bean id="personService" class="com.journaldev.spring.service.PersonServiceImpl">
<property name="personDAO" ref="personDAO"></property>
</bean>
<context:component-scan base-package="com.journaldev.spring" />
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
Usage:
import org.springframework.data.jpa.repository.JpaRepository;
import com.journaldev.spring.model.Person;
public interface PersonRepository extends JpaRepository<Person, Integer> {
}
Add to where to use:
@Autowired
private PersonRepository personRepository;
To add function to JpaRepository, we have 3 ways:
* Declare method name by combine keyword and fieldName
* Using NamedQuery
DAO Structure
Using JpaRepository and Entity Manager persistence |
Configuration:
<?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:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
">
<!-- Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven />
<jpa:repositories base-package="com.journaldev.spring.repository"/>
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources
in the /WEB-INF/views directory -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<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/spring-data-jpa" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
<property name="database" value="MYSQL"/>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<!-- spring based scanning for entity classes-->
<property name="packagesToScan" value="com.journaldev.spring.model"/>
</bean>
<bean id="personDAO" class="com.journaldev.spring.dao.PersonDAOImpl">
<property name="em" ref="entityManagerFactory" />
</bean>
<bean id="personService" class="com.journaldev.spring.service.PersonServiceImpl">
<property name="personDAO" ref="personDAO"></property>
</bean>
<context:component-scan base-package="com.journaldev.spring" />
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
Usage:
import org.springframework.data.jpa.repository.JpaRepository;
import com.journaldev.spring.model.Person;
public interface PersonRepository extends JpaRepository<Person, Integer> {
}
Add to where to use:
@Autowired
private PersonRepository personRepository;
To add function to JpaRepository, we have 3 ways:
* Declare method name by combine keyword and fieldName
public
List<Person> findByLastName(String lastName);
* Using NamedQuery
@Entity
@NamedQuery
(name =
"Person.findByName"
, query =
"SELECT p FROM Person p WHERE LOWER(p.lastName) = LOWER(?1)"
)
@Table
(name =
"persons"
)
public
class
Person {
@Id
@GeneratedValue
(strategy = GenerationType.AUTO)
private
Long id;
Then add method which name match namedQuery name:
public
List<Person> findByName(String lastName);
* Using @Query at method definition
@Query
(
"SELECT p FROM Person p WHERE LOWER(p.lastName) = LOWER(:lastName)"
)
public
List<Person> find(
@Param
(
"lastName"
) String lastName);
Entity Manager
@PersistenceContext
private EntityManager em;
@Override
public List<Person> findByCountry(String country) {
List<Person> results = em.createNamedQuery("findByCountry").setParameter(1, country).getResultList();
return results;
}
EntityManager allow to run native Sql by em.createNativeQuery(String sqlString).
References:
http://www.petrikainulainen.net/spring-data-jpa-tutorial/
Subscribe to:
Posts (Atom)