No WebApplicationContext found: no ContextLoaderListener registered?

ERROR: No WebApplicationContext found: no ContextLoaderListener registered?

Solution: Add spring-context

	<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework.version}</version>
	</dependency>	

Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

    <display-name>Spring-Hibernate-Template</display-name>
    
    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/login/*</url-pattern>
    </servlet-mapping>
    
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>contextAttribute</param-name>
            <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
	
    
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
	
	<error-page>
        <error-code>400</error-code>
        <location>/WEB-INF/jsp/error.jsp</location>
    </error-page>
    <error-page>
        <error-code>401</error-code>
        <location>/WEB-INF/jsp/error.jsp</location>
    </error-page>
    <error-page>
        <error-code>404</error-code>
        <location>/WEB-INF/jsp/error.jsp</location>
    </error-page>
    <error-page>
        <error-code>405</error-code>
        <location>/WEB-INF/jsp/error.jsp</location>
    </error-page>
    <error-page> 
    	<exception-type>java.lang.Throwable</exception-type> 
   	 	<location>/WEB-INF/jsp/error.jsp</location> 
	</error-page>
	<context-param>
        <param-name>defaultHtmlEscape</param-name>
        <param-value>true</param-value>
    </context-param>
</web-app>

Embedded DataSource HSQL for Junit Testing

Configure Embedded HSQL DataSource

package com.cloudbootstrap.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;

/**
 * The data source config that can be used in integration tests.
 */
@Configuration
@Profile("test")
public class EmbeddedDataSourceConfig implements DataSourceConfig {

    @Override
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.HSQL)
                .build();
    }
}

Test WebAppConfiguration with Embedded DataSource

package com.cloudbootstrap.config;

import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;

import javax.inject.Inject;

import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
@WebAppConfiguration
@ContextConfiguration(classes = {ApplicationConfig.class, EmbeddedDataSourceConfig.class, JpaConfig.class, SecurityConfig.class, WebMvcConfig.class})
public abstract class WebAppConfigurationAware {

    @Inject
    protected WebApplicationContext wac;
    protected MockMvc mockMvc;

    @Before
    public void before() {
        this.mockMvc = webAppContextSetup(this.wac).build();
    }

}

Spring Jpa different object already associated

ERROR: A different object with the same identifier value was already associated with the session

Solution: See if an existing ID already exist, if not persist record. If same ID found, merge with existing record

@Override
	@Transactional(value="dwTransactionManager", propagation=Propagation.REQUIRES_NEW)
	public void insertLog(Error[] errorRecords, Long recordId, String salesforceId, String objectName) {
		for (Error errorRecord : errorRecords){
			try {
				DWLog log = new DWLog();
				log.setId(new BigDecimal(recordId));
				Calendar cal = Calendar.getInstance();
				log.setLastSyncD(cal.getTime());
				log.setLastSyncMsg("ERROR CODE: " + errorRecord.getStatusCode() + " MESSAGE: " + errorRecord.getMessage());
				log.setObjectSync(objectName);
				if (entityManager.find(DWLog.class,log.Id)!=null){
					entityManager.merge(log);	
				}else{
					entityManager.persist(log);	
				}
			} catch (Exception e) {
				logger.error("LogDaoImpl.insertLog(): " + e.getMessage());
			}
		}
	}

Apex Code: Track Sales Rep Tasks and Set Follow Up Dates

public with sharing class SalesRepActivity  {
	
	public void updateSalesRepActivity(Set<Id> taskIds){
		try{
		
		for (Task task : [Select Id, Type, Subject, Status, AccountId, Account.Owner.Id, OwnerId, Detailed_Type__c from Task where Id IN : taskIds]){
			if (task.AccountId != null){
				if (task.Account.Owner.Id == task.OwnerId){
					Account accountToUpdate = new Account(Id=task.AccountId);

					if (task.type.equals('Sent Email') && task.subject.containsIgnoreCase('Mass Email:')){
						accountToUpdate.Last_Mass_Email__c = Date.today();
					}
					else if ((task.type.equals('Sent Email') || task.type.equals('Clearslide Email Pitch')) && task.subject.containsIgnoreCase('Email:')){
						accountToUpdate.Last_Non_Mass_Email__c = Date.today();
					}
					else if ((task.type.equals('Sent Email') && task.subject.containsIgnoreCase('re:')) && (task.Detailed_Type__c.equals('Connected') || task.Detailed_Type__c.equals('Meet') || task.Detailed_Type__c.equals('Meet outside'))){
						accountToUpdate.Last_Email_Connect__c = Date.today();
						accountToUpdate.Last_connected_date__c = Date.today();
					}
					else if (task.type.equals('Outbound Call') && task.status.equals('Completed') && task.Detailed_Type__c.equals('Connected')){
						accountToUpdate.Last_Call_Connect__c = Date.today();
						accountToUpdate.Last_connected_date__c = Date.today();
						accountToUpdate.Last_Call_attempt__c = Date.today();
					}
					else if (task.type.equals('Outbound Call')){
						accountToUpdate.Last_Call_attempt__c = Date.today();
					}
					else if (task.type.equals('Inbound Call')){
						accountToUpdate.Last_Call_attempt__c = Date.today();
						accountToUpdate.Last_connected_date__c = Date.today();
						accountToUpdate.Last_Call_Connect__c = Date.today();
					}

					update accountToUpdate;
				}
			}
		}

		}catch(Exception e){
			System.debug(e.getMessage());
		}
	}
}

Apex Update Case Priority when Bad Words in Incoming Email

Updating a case priority of a case when you receive a email with some words in the body that will make it more important. By looking at the words you can update the priority to high so Support reps can faster attend to those cases

public with sharing class CaseMatchIncomingEmail {
	public enum badWords {
		Frustrated,
		Frustrating,
		Angry,
		Mad,
		Annoyed,
		Annoying,
		Complain,
		Complaint,
		Lost,
		Upset,
		Awful,
		Bad,
		Mislead,
		Misleading,
		Fraud,
		Scam,
		request,
		SEC,
		transfer,
		Broken,
		Problem,
		Issue,
		Disappoint,
		Disappointing,
		Prosper,
		Lawsuit,
		Sue,
		Hate,
		Attorney,
		Discrepancy,
		Pissed,
		ridiculous,
		immediate,
		immediately,
		kidding,
		joking,
		joke}

	public void mathIncomingCaseEmail(List<Case> casesToUpdate) {
		List<Case> caseToUpdateList = new List<Case>();

		for (Case caseToUpdate : casesToUpdate){
			for (badWords badword : badWords.values()){
				if (caseToUpdate.Subject!=null){
					if (caseToUpdate.Subject.containsIgnoreCase(badword.name())){
						caseToUpdate.Priority = 'High';
					}
				}
				if (caseToUpdate.Description!=null){
					if (caseToUpdate.Description.containsIgnoreCase('disclaimer')){
						if (caseToUpdate.Description.lastIndexOf('disclaimer')>0){
							if (caseToUpdate.Description.substring(0,caseToUpdate.Description.lastIndexOf('disclaimer')).containsIgnoreCase(badword.name())){
							caseToUpdate.Priority = 'High';
							}
						}
					}
					else if (caseToUpdate.Description.containsIgnoreCase(badword.name())){
						caseToUpdate.Priority = 'High';
					}
				}
			}

			if (caseToUpdate.SuppliedEmail != null){
				List<List<SObject>> searchList = searchByField(caseToUpdate.SuppliedEmail);
				List<Contact> contactSearchList =  ((List<Contact>)searchList[0]);
				List<Admin_Member_ID_Account__c> adminMemberSearchList =  ((List<Admin_Member_ID_Account__c>)searchList[1]);

				if (contactSearchList.size() > 0){
					for (Contact contactSearchResult:contactSearchList){
						if (contactSearchResult.Email == caseToUpdate.SuppliedEmail){
							caseToUpdate.ContactId = contactSearchList.get(0).Id;
							caseToUpdate.AccountId = contactSearchList.get(0).AccountId;
						}
					}
				}
				if (adminMemberSearchList.size() > 0){
					for (Admin_Member_ID_Account__c adminMemberIdAccount : adminMemberSearchList){
						if (adminMemberIdAccount.AM_ID_Email__c == caseToUpdate.SuppliedEmail)
							caseToUpdate.AM_Member_ID__c = adminMemberSearchList.get(0).Id;
					}
				}
			}
		}
	}
}

Spring EntityManager createNativeQuery return Object[]

Scenario: You are lazy and don’t want to create an @Entity class and just want to query a few columns.

@PersistenceContext(unitName="dev")
EntityManager entityManager;

@SuppressWarnings("unchecked")
public List<Object[]> retrieveCustomerInfo(){
		try {
			return entityManager.createNativeQuery("select name, age from Customer").getResultList();
		} catch (Exception e) {
			logger.error("Customer Query Exception", e);
		}
		return null;
} 

public void invokeCustomerEndpointWithInfo(List<Object[]> customerInfo){
	Iterator<Object[]> it = customerInfo.iterator( );
        while (it.hasNext( )) {
			Object[] result = (Object[])it.next();
			String name = (String) result[0];
			Integer age = (Integer) result[1];
        }
}

Caching using Spring and Ehcache

Configure EhCache Cache Manager

package com.example.cache;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;

@Configuration
@EnableCaching
public class EhChacheConfiguration {
	
	@Bean
	public EhCacheManagerFactoryBean ehCahceFactory(){		
		EhCacheManagerFactoryBean ehCache = new EhCacheManagerFactoryBean();
		ehCache.setConfigLocation(new ClassPathResource("ehcache.xml"));
		ehCache.setCacheManagerName("customerCache");
		ehCache.setShared(true);
		return ehCache;
	}
	
	@Bean
	public EhCacheCacheManager cachceManager(EhCacheManagerFactoryBean ehCahceFactory){
		EhCacheCacheManager ehCacheCacheManager = new EhCacheCacheManager();
		ehCacheCacheManager.setCacheManager(ehCahceFactory.getObject());
		return ehCacheCacheManager;
	}
}

EhCache Configuration

<ehcache 
	xsi:noNamespaceSchemaLocation="ehcache.xsd" 
	updateCheck="true" 
	monitoring="autodetect" 
	dynamicConfig="true"
	maxBytesLocalHeap="150M"	
	>
	<diskStore path="java.io.tmpdir"/>	

	<cache name="customers"
	      maxBytesLocalHeap="40M"
	      eternal="false"
	      timeToIdleSeconds="300"
	      overflowToDisk="true"
	      maxEntriesLocalDisk="1000"
	      diskPersistent="false"
	      diskExpiryThreadIntervalSeconds="120"
	      memoryStoreEvictionPolicy="LRU"/>	 	      

</ehcache>

Cache Customer Service ~ Cached and CacheEvict

package com.example.jpa;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.example.service.CustomerService;
import com.example.model.Customer;
import com.googlecode.ehcache.annotations.Cacheable;
import com.googlecode.ehcache.annotations.TriggersRemove;

@Repository
@Qualifier("jpaRepository")
@Transactional(readOnly = true)
public class JpaCustomerService implements CustomerService {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    @Transactional(readOnly = true)
    @Cacheable(cacheName="CustomerCache")
    public Customer getCustomerById(BigInteger id) {
        return this.entityManager.find(Customer.class, id);
    }

    @Override
    @Transactional
    @CacheEvict(value = { "CustomerCache", "CustomerCache" }, allEntries = true, beforeInvocation = false)
    public Customer createCustomer(String fn, String ln) {
        Customer newCustomer = new Customer();
        newCustomer.setFirstName(fn);
        newCustomer.setLastName(ln);
        this.entityManager.persist(newCustomer);
        return newCustomer;
    }
   
    @Override
    @Cacheable(cacheName="CustomerCache")
	public Collection<Customer> getAllCustomers() {
		 CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
	     CriteriaQuery<Customer> criteriaBuilderQuery = criteriaBuilder.createQuery(Customer.class);
	     CriteriaQuery<Customer> customerCriteriaQuery = criteriaBuilderQuery.select(
	      criteriaBuilderQuery.from(Customer.class));
	     customerCriteriaQuery.orderBy(criteriaBuilder.asc(customerCriteriaQuery.from(Customer.class).get("id")));
	     return this.entityManager.createQuery(customerCriteriaQuery).getResultList();
	}

	@Override
	@Transactional
	@TriggersRemove(cacheName="CustomerCache", removeAll=true)
	public void deleteCustomer(BigInteger id) {
		this.entityManager.remove(this.entityManager.find(Customer.class, id));
	}
}

Heroku Elastic Search Example

Elastic search configuration

package com.example.elasticsearch;

import io.searchbox.client.JestClient;
import io.searchbox.client.JestClientFactory;
import io.searchbox.client.config.ClientConfig;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JestConfiguration {

	@Bean
	public JestClient jestClient(){
		// Configuration
		ClientConfig clientConfig = new ClientConfig.Builder(System.getenv("SEARCHBOX_URL"))
		.multiThreaded(true).build();

		// Construct a new Jest client according to configuration via factory
		JestClientFactory factory = new JestClientFactory();
		factory.setClientConfig(clientConfig);
		JestClient client = factory.getObject();
		return client;
	}
}

Elastic search service

package com.example.elasticsearch;

import java.util.List;

import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.core.Bulk;
import io.searchbox.core.Index;
import io.searchbox.core.Search;
import io.searchbox.indices.CreateIndex;
import io.searchbox.indices.IndicesExists;

import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Service;

import com.example.jpa.JpaCustomerService;
import com.example.model.Customer;
import com.example.service.CustomerService;

@Service
@Import(JpaCustomerService.class)
public class JestService {

	@Autowired @Qualifier("jpaRepository") CustomerService jpaCustomerService;
	
	@Autowired JestClient jestClient;
	
    @Autowired
	public void createCustomerIndex(){
		try {
			IndicesExists indicesExists = new IndicesExists.Builder().build();
	        JestResult result = jestClient.execute(indicesExists);

            if (!result.isSucceeded()) {
                // Create customer index
                CreateIndex createIndex = new CreateIndex.Builder("customers").build();
                jestClient.execute(createIndex);
            }
      
            Bulk bulk = new Bulk.Builder()
		 	.addAction(new Index.Builder(jpaCustomerService.getAllCustomers()).index("customer").type("customer").build())
		    .build();

            result = jestClient.execute(bulk);

            System.out.println(result.getJsonString());
	
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public List<Customer> searchCustomers(String customerQuery){
		try {
			SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
	        searchSourceBuilder.query(QueryBuilders.queryString(customerQuery));
	        
	        Search search = new Search.Builder(searchSourceBuilder.toString())
	        .addIndex("customer")
	        .addType("customer")
	        .build();
	
	        JestResult result = jestClient.execute(search);
			return result.getSourceAsObjectList(Customer.class);
		        
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 return null;
	}
}

MemCached CustomSerializingTranscoder Serialized Object

Was getting this error when I was trying to set a custom object:
memCachedClient.set(“customerObj”, 3600, new Customer(“John”, “Doe”));

2014-03-01 15:47:21.339 WARN net.spy.memcached.transcoders.SerializingTranscoder:  Caught CNFE decoding 150 bytes of data
2014-03-01T15:47:21.340137+00:00 app[web.1]: java.lang.ClassNotFoundException: com.example.model.Customer
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.security.AccessController.doPrivileged(Native Method)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.lang.Class.forName0(Native Method)
2014-03-01T15:47:21.340436+00:00 app[web.1]: 	at java.lang.Class.forName(Class.java:266)

This occurs because the memcached client is loaded using a classloader and the serialized object class is loaded using another classloader. To fix this you must pass to the memcahed client connector factory a custom transcoder.


 MemcachedClient mc = new MemcachedClient(
   new ConnectionFactoryBuilder()
   .setTranscoder(new CustomSerializingTranscoder()) //Add this line
   .setProtocol(ConnectionFactoryBuilder.Protocol.BINARY)
   .setAuthDescriptor(ad).build(),
package com.example.cache;

import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;

import net.spy.memcached.transcoders.SerializingTranscoder;

public class CustomSerializingTranscoder extends SerializingTranscoder{

    @Override
    protected Object deserialize(byte[] bytes) {
        final ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
        ObjectInputStream in = null;
        try {
            ByteArrayInputStream bs = new ByteArrayInputStream(bytes);
            in = new ObjectInputStream(bs) {
                @Override
                protected  Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {
                    try {
                        return currentClassLoader.loadClass(objectStreamClass.getName());
                    } catch (Exception e) {
                        return super.resolveClass(objectStreamClass);
                    }
                }
            };
            return in.readObject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            closeStream(in);
        }
    }

    private static void closeStream(Closeable c) {
        if (c != null) {
            try {
                c.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Spring Custom Profiles Configuration and Testing

@ActiveProfiles for Junit

import static org.junit.Assert.*;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;

import com.example.config.HerokuDataSourceConfiguration;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={JpaConfiguration.class, HerokuDataSourceConfiguration.class})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@ActiveProfiles(profiles={"heroku"})
@Transactional
public class CustomerJpaConfigTest {

	@PersistenceContext
	EntityManager entityManager;
	
	@Test
	public void testJpaConfiguration() {
		assertTrue(entityManager.isOpen());
	}

}

AnnotationConfigApplicationContext setActiveProfiles to active profile

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
    applicationContext.getEnvironment().setActiveProfiles("heroku");
    applicationContext.scan(JdbcDoaImpl.class.getPackage().getName());
    applicationContext.refresh();

Maven run test for active profile

mvn jetty:run -Dspring.profiles.active="heroku"
Follow

Get every new post delivered to your Inbox.

Join 215 other followers

%d bloggers like this: