Spring
References
Maven
pom.xml
<dependency>
<groupId>com.basho.riak</groupId>
<artifactId>riak-client</artifactId>
<version>1.4.4</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
- The exclusions are in place to avoid dependency tree conflicts
applicationContext.xml
<!-- Ignore Controllers -->
<context:component-scan base-package="com.ntg.sme">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
type="annotation" />
</context:component-scan>
<context:property-placeholder location="classpath:riak.properties" />
<bean id="riakClient" class="com.basho.riak.client.RiakFactory"
factory-method="httpClient">
<constructor-arg type="java.lang.String" value="${${environment}.riak.url}/riak" />
</bean>
<solr:repositories base-package="com.ntg.sme.webapp.repository"
multicore-support="true" />
<bean id="solrServer"
class="org.springframework.data.solr.server.support.HttpSolrServerFactoryBean">
<property name="url" value="${${environment}.riak.url}/solr" />
</bean>
<bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate">
<constructor-arg ref="solrServer" />
</bean>
- The Riak URL is read from a properties file
- /riak and /solr need to be appended to the the Riak and Solr URLs respectively
- In this case, an HttpClient is being used in place of PbcClient (load-balancer with Basic Authentication)
- The timeout property of the solr-server object was causing connection timeout issues (bizarrely a value of null works) so an HttpSolrServerFactoryBean is used instead
- In order to use multiple buckets (cores) for searching, set the multicore-support attribute to true
riak.properties
dev.riak.url=http://riak.ntg.sme.com
production.riak.url=http://riak.ntg.sme.com
- Add -Denvironment=dev/production as a startup parameter
Solr
XML
- Ensure that XML is parsed rather than the Java binary format (javabin):
@Override
public void afterPropertiesSet() throws Exception {
((HttpSolrServer) solrServer).setParser(new SmeResponseParser());
}
- Orginally this was XMLResponseParser but there was a problem with HttpSolrServer checking the content-type of the response (application/xml != text/xml)
- An SmeResponseParser was created to return text/xml:
import org.apache.solr.client.solrj.impl.XMLResponseParser;
public class SmeResponseParser extends XMLResponseParser {
public static final String XML_CONTENT_TYPE = "text/xml; charset=UTF-8";
public String getContentType() {
return XML_CONTENT_TYPE;
}
}
Query
SolrQuery query = new SolrQuery();
query.set("q", "identification_tradingAddress_postcode:WR7*");
QueryResponse rsp = solrServer.query(query);
Transform
- Convert the XML into an object:
List list = solrTemplate.convertQueryResponseToBeans(rsp, Compan.class);
Domain
- No nested structures (i.e. flat)
- Annotate fields with @Field if the field name differs from the XML
- Add a value to the @Field to map to the XML response; especially important for nested objects: @Field("identification_roAddress_add1")
- Add @Id to the identifier (unless the field is called Id, in which case no annotations are required
- Add @RiakKey to the identifier if the object is being saved in Riak
- Add @SolrDocument to identify the index (core) to use
@SolrDocument(solrCoreName = "company")
public class CompanySearch implements Serializable {
@Id
@Field("id")
private String company;
@Field("identification_alpha")
private String alpha;
@Field("identification_name")
private String name;
@Field("identification_roAddress_add1")
private String add1;
Logging
Maven
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
log4j.properties
log4j.rootLogger=DEBUG, solrLog
log4j.appender.solrLog=org.apache.log4j.ConsoleAppender
log4j.appender.solrLog.layout=org.apache.log4j.PatternLayout
log4j.appender.solrLog.layout.ConversionPattern=%-4r [%t] %-5p %c %x – %m%n
Dates
- Ensure dates are stored in a consistent manner for Solr and Riak. The @JsonFormat annotation ensures that the date is written in this format by jackson (required for InterConnect):
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZ")
private Date transaction_date;
- Specify the gson date format within InterConnect:
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create();
- Specify a global SimpleDateFormat (ISO 8601). This specifies that all dates are read and written in the format specified within a Spring web application:
<mvc:annotation-driven>
<mvc:message-converters register-defaults="false">
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.knappsack.swagger4springweb.util.ScalaObjectMapper">
<property name="serializationInclusion">
<value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value>
</property>
<property name="dateFormat">
<bean class="java.text.SimpleDateFormat" p:timeZone="GMT">
<constructor-arg value="yyyy-MM-dd'T'HH:mm:ssZ" />
<constructor-arg>
<bean class="java.util.Locale">
<constructor-arg index="0" value="en" />
<constructor-arg index="1" value="US" />
</bean>
</constructor-arg>
</bean>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
Repositories
public interface CompanyRepository extends Repository<Company, String> {
List findByNameLike(String name);
}
No comments:
Post a Comment