Thursday, December 25, 2014

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
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/ 

Saturday, June 28, 2014

Changes from Liferay 6.1 to 6.2

  • ThemeSetting:
In liferay-look-and-feel .xml:
<setting configurable="true" key="header-banner" type="textarea" value=""/>

In portal_normal.vm:
#set($bg_header = $theme_display.getThemeSetting("header-banner"))

In this case, we use $theme_display.getThemeSetting(key)  instead of $theme.getSetting(key)

  • Ajax using AUI:
AUI().use('node','aui-base','aui-io-request', function(A) {
        var groupId = A.one('#' + namespace + "groupId").get("value");
        A.io.request(ajaxPageLayoutUrl, {
            dataType : 'json',
            data : {
                <portlet:namespace/>groupId: groupId
            },
            on : {
                success : function() {
                    var data = this.get('responseData');
                    for(var i = 0; i < data.length; i++) {
                        var page = data[i];
                        var selected = page.plid == curPageSelected ? "selected" : "";
                        var newOption = A.Node.create('<option value="' + page.plid + '"' + selected + '>'+ page.title +'</option>');
                        A.one('#' + namespace + "plid").appendChild(newOption);
                    }
                }
            }
        });
    });

Friday, June 27, 2014

Accessing Service and Util in Application Display Template



See: (in content and comment)

1. http://liferaytrends.blogspot.com/2012/05/access-liferay-service-util-and-custom.html

2. http://stackoverflow.com/questions/12106827/liferay-obtain-filesize-in-template

Sunday, June 22, 2014

Using Application Display Template in (ADT) Liferay 6.2

If you want to get portlet title in ADT, using this code snippets:

#set ($portletTitle = $themeDisplay.getPortletDisplay().getTitle())

If you want to use localization, using code like this:

$languageUtil.get($locale, "read-more")