Set last_modified field when not defined in document in Solr - apache

I'm using Solr 4.6 example's SimplePostTool to import documents from the filesystem to Solr. All it's ok, but the field last_modified is filled only when the original document has metadata for it. If the field is not present Solr extractor leaves the field blank.
I tried to modify SimplePostTool to set this field using the file system modification date, but then I get this error when I try to import files that already have last_modified field from the metadata:
430584 [qtp1214238505-16] ERROR org.apache.solr.core.SolrCore –
org.apache.solr.common.SolrException: ERROR:
[doc=4861976] multiple values encountered for non multiValued field
last_modified: [2013-12-22T14:03:10.000Z, 2013-07-02T11:29:20.000Z]
I'm thinking about using a custom field for file system date, but in my case, metadata date if preferable when is available. Is there any way to merge them at import time?
Thanks!

You can set a default value in your schema. Something like this should work:
<field name="my_date" type="date" indexed="true" stored="true" multiValued="false" default="NOW" />
Field Type Definition:
<fieldType name="date" class="solr.TrieDateField" sortMissingLast="true" omitNorms="true"/>

while creating a document the solr takes all input as text and then validates according to the given data type , Hence any form of valid date format accepted ,would work fine with the solr .
For current time
Any default value
regards
Rajat

I finally solved the issue creating a custom Update Request Processor, as explained here: http://wiki.apache.org/solr/UpdateRequestProcessor
My processor is as follows:
package com.mycompany.solr;
import java.io.IOException;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.update.AddUpdateCommand;
import org.apache.solr.update.processor.UpdateRequestProcessor;
import org.apache.solr.update.processor.UpdateRequestProcessorFactory;
public class LastModifiedMergeProcessorFactory
extends UpdateRequestProcessorFactory {
#Override
public UpdateRequestProcessor getInstance(SolrQueryRequest req,
SolrQueryResponse rsp, UpdateRequestProcessor next) {
return new LastModifiedMergeProcessor(next);
}
}
class LastModifiedMergeProcessor extends UpdateRequestProcessor {
public LastModifiedMergeProcessor(UpdateRequestProcessor next) {
super(next);
}
#Override
public void processAdd(AddUpdateCommand cmd) throws IOException {
SolrInputDocument doc = cmd.getSolrInputDocument();
Object metaDate = doc.getFieldValue( "last_modified" );
Object fileDate = doc.getFieldValue( "file_date" );
if( metaDate == null && fileDate != null) {
doc.addField( "last_modified", fileDate );
}
// pass it up the chain
super.processAdd(cmd);
}
}
Where file_date is a field I set with the file modification date at import time.

Related

Liquibase: how to generate a value for a column while parsing

I would like to programmatically generate a value (id) for a column during an insert using a Liquibase changelog (XML). For example:
<changeSet ...>
<preConditions ...>
<insert tableName="my_table">
<column name="my_id" value="<call-code-to-generate-id>" />
...
</insert>
I need to do this programmatically because the id needs a character prefix (determined by code) followed by a sequence number (legacy code and lots of other components in the system use it). The changelog needs to support both Oracle and SQL Server, and sequence numbers are generated differently (the code currently handles this).
I have looked at ChangeLogParser and SqlGenerator but I'm not seeing an easy way to do this. I was thinking it might be possible to parse the XML looking for 'value='' and replace the value with a generated id, but I'm not sure the effect this would have on Liquibase to determine if the changelog has been updated or not.
Does anyone know if this is possible and if so, how to do this?
I'm using Liquibase 3.5.3 and Java 8.
I got this working using a subclass of the Liquibase class InsertDataChange. I put the class in the package liquibase.sqlgenerator.ext so that Liquibase automatically registers it.
package liquibase.sqlgenerator.ext;
import liquibase.change.ColumnConfig;
import liquibase.change.core.InsertDataChange;
import liquibase.database.Database;
import liquibase.statement.SqlStatement;
public class MyInsertDataChange extends InsertDataChange {
#Override
public SqlStatement[] generateStatements(final Database database) {
for (final ColumnConfig column : getColumns()) {
final String tableName = getTableName();
final String name = column.getName();
final String value = column.getValue();
if (columnNeedsId(tableName, name, value)) {
column.setValue(generateId(tableName, name, value));
}
}
return super.generateStatements(database);
}
private boolean columnNeedsId(final String tableName, final String name, final String value) {
// Details omitted
return true;
}
private String generateId(final String tableName, final String name, final String value) {
// Details omitted
final String sequenceName = "whatever";
final long sequenceNumber = 123L;
return sequenceName + sequenceNumber;
}
}

Sonar Custom Widget

I created a widget using the source code available in github. Now I'm using that widget in SonarQube V5.3. This is where I got the source code from:
https://github.com/SonarSource/sonar-examples/tree/master/plugins/sonar-reference-plugin
When I use this widget it is showing up the same data across multiple projects. I would like to know if there is any way I can display different data for different projects. Please share your ideas. Below is the code that displays the ruby widget
import org.sonar.api.web.AbstractRubyTemplate;
import org.sonar.api.web.Description;
import org.sonar.api.web.RubyRailsWidget;
import org.sonar.api.web.UserRole;
import org.sonar.api.web.WidgetCategory;
import org.sonar.api.web.WidgetProperties;
import org.sonar.api.web.WidgetProperty;
import org.sonar.api.web.WidgetPropertyType;
import org.sonar.api.batch.CheckProject;
import org.sonar.api.resources.Project;
#UserRole(UserRole.USER)
#Description("Sample")
#WidgetCategory("Sample")
#WidgetProperties({
#WidgetProperty(key = "Index",type=WidgetPropertyType.TEXT
),
})
public class OneMoreRubyWidget extends AbstractRubyTemplate implements RubyRailsWidget {
#Override
public String getId() {
return "Sample";
}
#Override
public String getTitle() {
return "Sample";
}
#Override
protected String getTemplatePath() {
return "/example/Index.html.erb";
}
}
Thank you so much in advance
You haven't specified global scope for your widget (#WidgetScope("GLOBAL")) in the .java file, so this is a question of what's in your .erb file.
This Widget Lab property widget should give you some pointers. Specifically: you want to pick up #project in your widget, and query with #project.uuid. Here's another project-level widget for comparison.
You should be aware, though, that SonarSource is actively working to remove Ruby from the platform, so at some future date, you'll probably end up re-writing your widgets (likely in pure JavaScript).

Need help about #Get #Post #Put #Delete in Restful webservice

I need your help and advice. This is my first project in jersey. I don't know much about this topic. I'm still learning. I created my school project. But I have some problems on the web service side. Firstly I should explain my project. I have got 3 tables in my database. Movie,User,Ratings
Here my Movie table columns. I will ask you some points about Description column of the Movie table. I will use these methods to these columns.
Movie= Description (get,put,post and delete) I have to use all methods in this page.
movieTitle (get)
pictureURL (get,put)
generalRating (get,post)
I built my Description page. But I'm not sure if its working or not .(My database is not ready to check them). Here is my page. I wrote this page, looking at the example pages. Can u help me to find the problems and errors. I just want to do simple methods get(just reading data), post(update existing data), put(create new data), delete(delete specific data) these things.What should I do now, is my code okay or do you have alternative advice? :( I need your help guys ty
package com.vogella.jersey.first;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.List;
import javax.ejb.*;
import javax.persistence.*;
import javax.ws.rs.*;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.PUT;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
#Path("/Movie/Description")
public class Description {
private Moviedao moviedao = new Moviedao();
#GET
#Path("/Description/")
#Produces(MediaType.APPLICATION_XML)
public Description getDescriptionID(#PathParam("sample6") string sample6){
return moviedao.getDescriptionID(id);
}
#POST
#Path("/Description/")
#Produces(MediaType.APPLICATION_XML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void updateDescription(#PathParam("sampleID")int sampleID,
#PathParam("sample2Description")string sample2Description)
throws IOException {
Description description = new Description (sampleID, sample2Description);
int result = moviedao.updateDescription(description);
if(result == 1){
return SUCCESS_RESULT;
}
return FAILURE_RESULT;
}
#PUT
#Path("/Description")
#Produces(MediaType.APPLICATION_XML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String createUser(#FormParam("sample8ID") int sample8ID,
#FormParam("sample8Description") String sample8Description,
#Context HttpServletResponse servletResponse) throws IOException{
Description description = new Description (sample8ID, sample8Description);
int result = movidao.addDescription(description);
if(result == 1){
return SUCCESS_RESULT;
}
return FAILURE_RESULT;
}
#DELETE
#Path("/Description/{descriptionID}")
#Produces(MediaType.APPLICATION_XML)
public String deleteUser(#PathParam("descriptionID") int descriptionID){
int result = moviedao.deleteDescription(descriptionID);
if(result == 1){
return SUCCESS_RESULT;
}
return FAILURE_RESULT;
}
#OPTIONS
#Path("/Description")
#Produces(MediaType.APPLICATION_XML)
public String getSupportedOperations(){
return "<operations>GET, PUT, POST, DELETE</operations>";
}
}
I just want to do simple methods get(just reading data), post(update
existing data), put(create new data), delete(delete specific data)
these things
POST should be used to create resources and PUT should be used to update resources.
Your class already has webservice path /Movie/Description, so there is no need to repeat word Description in the methods.
Also, I would recommend keep path names in lower case e.g. /movie/description

In JSF,how to get parameter values form my sql to jsf the page?

I first made a sql, zdsql, for this project:
create table zdsql(
id integer primary key,
filter varchar(12),
value varchar(12),
descri varchar(12),
standard_number integer,
language varchar(12)
);
insert into zdsql values(1,'zdlj','1','1.rid',1,'en');
insert into zdsql values(2,'zdlj','2','2.ria',1,'en');
Next, I made the JSF, the following codes is the maining of my xhtml:
<h:outputLabel value="#{msgs.zdlj}" style="font-weight:bold" />
<p:selectOneMenu id="zdlj1" value="#{zsjBean.zdlj}">
<f:selectItems value="#{zdsqlBean.zdsqls}" var="bll1"
itemLabel="#{bll1.descri}" itemValue="#{bll1.value}" />
</p:selectOneMenu>
The follwing codes is the maining of zdsqlBean:
package bean;
import java.util.List;
import java.util.logging.Level;
import javax.persistence.TypedQuery;
import model.Zdsql;
import util.DBDAO;
public class ZdsqlBean {
private List<Zdsql> zdsqls;
public ZdsqlBean() {
this.genzdljs();
}
public List<Zdsql> getZdsqls() {
System.out.println("zdsqls==");
return zdsqls;
}
public void setZdsqls(List<Zdsql> zdsqls) {
this.zdsqls = zdsqls;
}
public void genzdljs() {
try {
String queryString = "select m from Zdsql m where m.filter = :filter Order by m.id";
TypedQuery<Zdsql> query = DBDAO.getEntityManager().createQuery(
queryString, Zdsql.class);
query.setParameter("filter", "zdlj");
zdsqls = query.getResultList();
} catch (Exception re) {
DBDAO.log("genzdljs() failed", Level.SEVERE, re);
}
}
However, I still don't get the right values. When I run this project, the selectonemenu has nothing, which should have two selectitems, the values should be same as sql.
From comments, the problem is that you haven't configured the ZdsqlBean as managed bean. There are two ways to do this:
Add the configuration in faces-config.xml file:
<managed-bean>
<managed-bean-name>zdsqlBean</managed-bean-name>
<managed-bean-class>bean.ZdsqlBean</managed-bean-class>
<managed-bean-scope>none</managed-bean-scope>
</managed-bean>
Since JSF 2, use the #ManagedBean annotation to decorate the class.
#ManagedBean(name="zdsqlBean") //name is optional
public class ZdsqlBean {
//class definition
}
This is covered in a decent JSF tutorial, you can find some in StackOverflow JSF wiki. If you're learning/reading JSF 1.x resources, drop them and go with JSF 2. Note that currently it's in version 2.2.
Thanks Polppan a lot! I add ManagedBean in faces-config.xml, then I get the right result! Thanks for everyone's help!
But I firstly used this website, could you tell me how to close the question and choose the best answer?

How do I create a custom directive for Apache Velocity

I am using Apache's Velocity templating engine, and I would like to create a custom Directive. That is, I want to be able to write "#doMyThing()" and have it invoke some java code I wrote in order to generate the text.
I know that I can register a custom directive by adding a line
userdirective=my.package.here.MyDirectiveName
to my velocity.properties file. And I know that I can write such a class by extending the Directive class. What I don't know is how to extend the Directive class -- some sort of documentation for the author of a new Directive. For instance I'd like to know if my getType() method return "BLOCK" or "LINE" and I'd like to know what should my setLocation() method should do?
Is there any documentation out there that is better than just "Use the source, Luke"?
On the Velocity wiki, there's a presentation and sample code from a talk I gave called "Hacking Velocity". It includes an example of a custom directive.
Also was trying to come up with a custom directive. Couldn't find any documentation at all, so I looked at some user created directives: IfNullDirective (nice and easy one), MergeDirective as well as velocity build-in directives.
Here is my simple block directive that returns compressed content (complete project with some directive installation instructions is located here):
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.TemplateInitException;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.runtime.log.Log;
import com.googlecode.htmlcompressor.compressor.HtmlCompressor;
/**
* Velocity directive that compresses an HTML content within #compressHtml ... #end block.
*/
public class HtmlCompressorDirective extends Directive {
private static final HtmlCompressor htmlCompressor = new HtmlCompressor();
private Log log;
public String getName() {
return "compressHtml";
}
public int getType() {
return BLOCK;
}
#Override
public void init(RuntimeServices rs, InternalContextAdapter context, Node node) throws TemplateInitException {
super.init(rs, context, node);
log = rs.getLog();
//set compressor properties
htmlCompressor.setEnabled(rs.getBoolean("userdirective.compressHtml.enabled", true));
htmlCompressor.setRemoveComments(rs.getBoolean("userdirective.compressHtml.removeComments", true));
}
public boolean render(InternalContextAdapter context, Writer writer, Node node)
throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {
//render content to a variable
StringWriter content = new StringWriter();
node.jjtGetChild(0).render(context, content);
//compress
try {
writer.write(htmlCompressor.compress(content.toString()));
} catch (Exception e) {
writer.write(content.toString());
String msg = "Failed to compress content: "+content.toString();
log.error(msg, e);
throw new RuntimeException(msg, e);
}
return true;
}
}
Block directives always accept a body and must end with #end when used in a template. e.g. #foreach( $i in $foo ) this has a body! #end
Line directives do not have a body or an #end. e.g. #parse( 'foo.vtl' )
You don't need to both with setLocation() at all. The parser uses that.
Any other specifics i can help with?
Also, have you considered using a "tool" approach? Even if you don't use VelocityTools to automatically make your tool available and whatnot, you can just create a tool class that does what you want, put it in the context and either have a method you call to generate content or else just have its toString() method generate the content. e.g. $tool.doMyThing() or just $myThing
Directives are best for when you need to mess with Velocity internals (access to InternalContextAdapter or actual Nodes).
Prior to velocity v1.6 I had a #blockset($v)#end directive to be able to deal with a multiline #set($v) but this function is now handled by the #define directive.
Custom block directives are a pain with modern IDEs because they don't parse the structure correctly, assuming your #end associated with #userBlockDirective is an extra and paints the whole file RED. They should be avoided if possible.
I copied something similar from the velocity source code and created a "blockset" (multiline) directive.
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.TemplateInitException;
import java.io.Writer;
import java.io.IOException;
import java.io.StringWriter;
public class BlockSetDirective extends Directive {
private String blockKey;
/**
* Return name of this directive.
*/
public String getName() {
return "blockset";
}
/**
* Return type of this directive.
*/
public int getType() {
return BLOCK;
}
/**
* simple init - get the blockKey
*/
public void init( RuntimeServices rs, InternalContextAdapter context,
Node node )
throws TemplateInitException {
super.init( rs, context, node );
/*
* first token is the name of the block. I don't even check the format,
* just assume it looks like this: $block_name. Should check if it has
* a '$' or not like macros.
*/
blockKey = node.jjtGetChild( 0 ).getFirstToken().image.substring( 1 );
}
/**
* Renders node to internal string writer and stores in the context at the
* specified context variable
*/
public boolean render( InternalContextAdapter context, Writer writer,
Node node )
throws IOException, MethodInvocationException,
ResourceNotFoundException, ParseErrorException {
StringWriter sw = new StringWriter(256);
boolean b = node.jjtGetChild( 1 ).render( context, sw );
context.put( blockKey, sw.toString() );
return b;
}
}