Solr custom query component does not return correct facet counts - plugins

I have a simple Solr query component as follows:
public class QueryPreprocessingComponent extends QueryComponent implements PluginInfoInitialized {
private static final Logger LOG = LoggerFactory.getLogger( QueryPreprocessingComponent.class );
private ExactMatchQueryProcessor exactMatchQueryProcessor;
public void init( PluginInfo info ) {
initializeProcessors(info);
}
private void initializeProcessors(PluginInfo info) {
List<PluginInfo> queryPreProcessors = info.getChildren("queryPreProcessors")
.get(0).getChildren("queryPreProcessor");
for (PluginInfo queryProcessor : queryPreProcessors) {
initializeProcessor(queryProcessor);
}
}
private void initializeProcessor(PluginInfo queryProcessor) {
QueryProcessorParam processorName = QueryProcessorParam.valueOf(queryProcessor.name);
switch(processorName) {
case ExactMatchQueryProcessor:
exactMatchQueryProcessor = new ExactMatchQueryProcessor(queryProcessor.initArgs);
LOG.info("ExactMatchQueryProcessor initialized...");
break;
default: throw new AssertionError();
}
}
#Override
public void prepare( ResponseBuilder rb ) throws IOException
{
if (exactMatchQueryProcessor != null) {
exactMatchQueryProcessor.modifyForExactMatch(rb);
}
}
#Override
public void process(ResponseBuilder rb) throws IOException
{
// do nothing - needed so we don't execute the query here.
return;
}
}
This works as expected functionally except when I use this in a distributed request, it has an issue with facets counts returned. It doubles the facet counts.
Note that I am not doing anything related to faceting in plugin. exactMatchQueryProcessor.modifyForExactMatch(rb); does a very minimal processing if the query is quoted otherwise it does nothing. Even if the incoming query is not quoted, facet count issue is there. Even if I comment everything inside prepare function, issue persists.
Note that this component is declared in as first-components in solrconfig.xml.

I resolved this issue by extending the class to SearchComponent instead of QueryComponent. It seems that SearchComponent sits at higher level of abstraction than QueryComponent and is useful when you want to work on a layer above shards.

Related

Eclipse JDT ListRewrite inserts new node at wrong places

I'm trying to add an annotation to some selected fields using Eclipse JDT infrastructure. However, this is not run as a plugin. I added all the required dependencies to a separate project so this can be run in batch mode. However I found out that, the ListRewrite is not inserting my annotation at the right place. I have given the code below. I initially get all the field declarations in a map using a visitor and then add them one by one using the code below.
FieldDeclaration fld = lVrblDet.listStringVarMap.get(propName);
final MarkerAnnotation autoWiredAnnotate = ast.newMarkerAnnotation(); autoWiredAnnotate.setTypeName(ast.newName("MyAnnot"));
lrw = rewriter.getListRewrite(fld, FieldDeclaration.MODIFIERS2_PROPERTY);
lrw.insertLast(autoWiredAnnotate, null);
Document document = new Document(cu.toString());
try {
TextEdit edits = rewriter.rewriteAST(document, null);
edits.apply(document);
} catch (MalformedTreeException | IllegalArgumentException | BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
However the expected output is sometimes offset by 1 character.The input and output classes have been given below.
Input Class:
#SuppressWarnings("unchecked")
public class SampleClassA {
public SampleClassB classB;
public SampleClassB getClassB() {
return classB;
}
public void setClassB(SampleClassB classB) {
this.classB = classB;
}
#Deprecated
public void printNameFromSmapleClassB() {
System.out.println(this.classB.name);
}
}
Output Class:
#SuppressWarnings("unchecked") public class SampleClassA {
p #MyAnnot
ublic SampleClassB classB;
public SampleClassB getClassB(){
return classB;
}
public void setClassB( SampleClassB classB){
this.classB=classB;
}
#Deprecated public void printNameFromSmapleClassB(){
System.out.println(this.classB.name);
}
}
As you can see in the code above, the Annotation messed with the modifier. I have tried multiple combinations of insertFirst,insertLast.Examples on the net are incomplete. Can somebody point me the mistake/the right resource ?
I just couldn't get it to work with ListRewrite. I don't know what I was doing wrong. So I wrote a visitor to store all the FieldDeclarations in a map.
#Override
public boolean visit(FieldDeclaration node) {
for (Object obj : node.fragments()) {
listStringVarMap.put(((VariableDeclarationFragment) obj).getName().toString(), node);
}
return false;
}
I looped through the map and inserted the annotation nodes as a modifiers, for the declarations that met my criteria. Please do remember to turn on recormodifications for the compilation unit you are modifying.
CompilationUnit cu = jFileAst.getEquivCompilUnit();
cu.recordModifications();
FieldDeclaration fldDecl = lVrblDet.listStringVarMap.get(propName);
importVo = (JavaAnnotImportVo) javaAstNodeCreator
.createASTNode(SpringAnnotationEnum.AutowireAnnotation, ast);
cu.imports().add(importVo.getImpDecl());
fldDecl.modifiers().add(0, importVo.getAnnotNode());
Finally write to file on disk/save back. Formatting(optional) before saving is a good idea, because the node insertions mess up with the code formatting.

How to override installed mappings of Behavior?

In java-9 Skins made it into public scope, while Behaviors are left in the dark - nevertheless changed considerably, in now using InputMap for all input bindings.
CellBehaviorBase installs mouse bindings like:
InputMap.MouseMapping pressedMapping, releasedMapping;
addDefaultMapping(
pressedMapping = new InputMap.MouseMapping(MouseEvent.MOUSE_PRESSED, this::mousePressed),
releasedMapping = new InputMap.MouseMapping(MouseEvent.MOUSE_RELEASED, this::mouseReleased),
new InputMap.MouseMapping(MouseEvent.MOUSE_DRAGGED, this::mouseDragged)
);
A concrete XXSkin now installs the behavior privately:
final private BehaviorBase behavior;
public TableCellSkin(TableCell control) {
super(control);
behavior = new TableCellBehavior(control);
....
}
The requirement is replace the mousePressed behavior (in jdk9 context). The idea is to grab super's field reflectively, dispose all its mappings and install the custom behavior. For some reason that I don't understand, the old bindings are still active (though the old mappings are empty!) and are invoked before the new bindings.
Below is a runnable example to play with: the mapping to mousePressed is simply implemented to do nothing, particularly to not invoke super. To see the old bindings at work, I set a conditional debug breakpoint at CellBehaviorBase.mousePressed like (in Eclipse):
System.out.println("mousePressed super");
new RuntimeException("whoIsCalling: " + getNode().getClass()).printStackTrace();
return false;
Run a debug and click into any cell, then the output is:
mousePressed super
java.lang.RuntimeException: whoIsCalling: class de.swingempire.fx.scene.control.cell.TableCellBehaviorReplace$PlainCustomTableCell
at com.sun.javafx.scene.control.behavior.CellBehaviorBase.mousePressed(CellBehaviorBase.java:169)
at com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
//... lots more of event dispatching
// until finally the output in my custom cell behavior
Feb. 02, 2016 3:14:02 NACHM. de.swingempire.fx.scene.control.cell.TableCellBehaviorReplace$PlainCustomTableCellBehavior mousePressed
INFORMATION: short-circuit super: Bulgarisch
I would expect to only see the very last part, that is the printout by my custom behavior. It feels like I'm somehow fundamentally off - but can't nail it. Ideas?
The runnable code (sorry for its length, most is boiler-plate, though):
public class TableCellBehaviorReplace extends Application {
private final ObservableList<Locale> locales =
FXCollections.observableArrayList(Locale.getAvailableLocales());
private Parent getContent() {
TableView<Locale> table = createLocaleTable();
BorderPane content = new BorderPane(table);
return content;
}
private TableView<Locale> createLocaleTable() {
TableView<Locale> table = new TableView<>(locales);
TableColumn<Locale, String> name = new TableColumn<>("Name");
name.setCellValueFactory(new PropertyValueFactory<>("displayName"));
name.setCellFactory(p -> new PlainCustomTableCell<>());
TableColumn<Locale, String> lang = new TableColumn<>("Language");
lang.setCellValueFactory(new PropertyValueFactory<>("displayLanguage"));
lang.setCellFactory(p -> new PlainCustomTableCell<>());
table.getColumns().addAll(name, lang);
return table;
}
/**
* Custom skin that installs custom Behavior. Note: this is dirty!
* Access super's behavior, dispose to get rid off its handlers, install
* custom behavior.
*/
public static class PlainCustomTableCellSkin<S, T> extends TableCellSkin<S, T> {
private BehaviorBase<?> replacedBehavior;
public PlainCustomTableCellSkin(TableCell<S, T> control) {
super(control);
replaceBehavior();
}
private void replaceBehavior() {
BehaviorBase<?> old = (BehaviorBase<?>) invokeGetField(TableCellSkin.class, this, "behavior");
old.dispose();
// at this point, InputMap mappings are empty:
// System.out.println("old mappings: " + old.getInputMap().getMappings().size());
replacedBehavior = new PlainCustomTableCellBehavior<>(getSkinnable());
}
#Override
public void dispose() {
replacedBehavior.dispose();
super.dispose();
}
}
/**
* Custom behavior that's meant to override basic handlers. Here: short-circuit
* mousePressed.
*/
public static class PlainCustomTableCellBehavior<S, T> extends TableCellBehavior<S, T> {
public PlainCustomTableCellBehavior(TableCell<S, T> control) {
super(control);
}
#Override
public void mousePressed(MouseEvent e) {
if (true) {
LOG.info("short-circuit super: " + getNode().getItem());
return;
}
super.mousePressed(e);
}
}
/**
* C&P of default tableCell in TableColumn. Extended to install custom
* skin.
*/
public static class PlainCustomTableCell<S, T> extends TableCell<S, T> {
public PlainCustomTableCell() {
}
#Override protected void updateItem(T item, boolean empty) {
if (item == getItem()) return;
super.updateItem(item, empty);
if (item == null) {
super.setText(null);
super.setGraphic(null);
} else if (item instanceof Node) {
super.setText(null);
super.setGraphic((Node)item);
} else {
super.setText(item.toString());
super.setGraphic(null);
}
}
#Override
protected Skin<?> createDefaultSkin() {
return new PlainCustomTableCellSkin<>(this);
}
}
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(new Scene(getContent(), 400, 200));
primaryStage.setTitle(FXUtils.version());
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
/**
* Reflectively access super field.
*/
public static Object invokeGetField(Class source, Object target, String name) {
try {
Field field = source.getDeclaredField(name);
field.setAccessible(true);
return field.get(target);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
#SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(TableCellBehaviorReplace.class.getName());
}
Edit
The suggestion inherit from the abstract skin XXSkinBase instead of the concrete XXSkin (then you are free to install whatever behavior you want, dude :-) is very reasonable and should be the first option. In the particular case of XX being TableCell, that's currently not possible, as the base class contains abstract package-private methods. Also, there are XX that don't have an abstract base (like f.i. ListCell).
Might be a bug in InputMap:
Digging into the sources I found some internal book-keeping (eventTypeMappings) parallel to mappings (these are the handlers). InputMap is listening to changes in mappings and updates the internal book-keeping on changes
mappings.addListener((ListChangeListener<Mapping<?>>) c -> {
while (c.next()) {
// TODO handle mapping removal
if (c.wasRemoved()) {
for (Mapping<?> mapping : c.getRemoved()) {
removeMapping(mapping);
}
}
// removeMapping
private void removeMapping(Mapping<?> mapping) {
// TODO
}
Meaning that the internal structure is never cleaned, particularly not when the mappings are removed in behavior.dispose(). When looking up eventHandlers - by inputMap.handle(e), see debug stacktrace shown in the question - the old handler is found in the internal book-keeping structure.
Joys of early experiments ... ;-)
At the end, a (very dirty, very hacky!) solution is to take over InputMap's job and force a cleanup of the internals:
private void replaceBehavior() {
BehaviorBase<?> old = (BehaviorBase<?>) invokeGetField(TableCellSkin.class, this, "behavior");
old.dispose();
cleanupInputMap(old.getInputMap());
// at this point, InputMap mappings are empty:
// System.out.println("old mappings: " + old.getInputMap().getMappings().size());
replacedBehavior = new PlainCustomTableCellBehavior<>(getSkinnable());
}
/**
* This is a hack around InputMap not cleaning up internals on removing mappings.
* We remove MousePressed/MouseReleased/MouseDragged mappings from the internal map.
* Beware: obviously this is dirty!
*
* #param inputMap
*/
private void cleanupInputMap(InputMap<?> inputMap) {
Map eventTypeMappings = (Map) invokeGetField(InputMap.class, inputMap, "eventTypeMappings");
eventTypeMappings.remove(MouseEvent.MOUSE_PRESSED);
eventTypeMappings.remove(MouseEvent.MOUSE_RELEASED);
eventTypeMappings.remove(MouseEvent.MOUSE_DRAGGED);
}
BTW: just in case anybody is wondering wtf - without, my hack around the missing commitOnFocusLost when editing a cell stopped working in java-9.
Try in PlainCustomTableCellSkin to inherit from the abstract class TableCellSkinBase rather than from TableCellSkin.
Then you can call the super constructor, which takes an TableCellBehaviorBase object as additional param.
Then you can save your time replacing it, by initializing it directly with the right one.
Just for more claryfication:
TableCellSkin extends TableCellSkinBase
TableCellBehavior extends TableCellBehaviorBase
One more thing. You need to also call super.init(tableCell) in your constructor.
Take the TableCellSkin class as reference.

One shot ChangeListener in JavaFX

Is there any way to make a listener fire once and remove itself?
for(Spec spec : specs){
spec.myProperty().addListener((obs,ov,nv) -> {
if (nv.longValue() > 0){
//do whatever
spec.myProperty().removeListener(this);
}
});
}
That code won't work. I can only think of complicated solutions to this seemingly simple problem.
How about using an anonymous inner class instead of a lambda expression?
IntegerProperty property = new SimpleIntegerProperty();
InvalidationListener listener = new InvalidationListener() {
#Override
public void invalidated(Observable observable) {
//TODO do something
property.removeListener(this);
}
};
property.addListener(listener);
The answer was partly in the comments so I'll add my [brian] solution here.
public void someMethod(){
for(Spec spec : specs){
spec.myProperty().addListener(listener);
}
}
ChangeListener<Number> listener = new ChangeListener<Number>() {
public void changed(ObservableValue<? extends Number> obs, Number ov, Number nv) {
Spec spec = (Spec)((SimpleLongProperty)obs).getBean();
spec.myProperty().removeListener(this);
}
};
Note, when I create myProperty in the Spec class I use the full constructor to specify the bean. new SimpleLongProperty(this, "myProperty", 0l);
Even doing this you still can't use a lambda to remove this.

Get and Set attribute values of a class using aspectJ

I am using aspectj to add some field to a existing class and annotate it also.
I am using load time weaving .
Example :- I have a Class customer in which i am adding 3 string attributes. But my issues is that I have to set some values and get it also before my business call.
I am trying the below approach.
In my aj file i have added the below, my problem is in the Around pointcut , how do i get the attribute and set the attribute.
public String net.customers.PersonCustomer.getOfflineRiskCategory() {
return OfflineRiskCategory;
}
public void net.customers.PersonCustomer.setOfflineRiskCategory(String offlineRiskCategory) {
OfflineRiskCategory = offlineRiskCategory;
}
public String net.customers.PersonCustomer.getOnlineRiskCategory() {
return OnlineRiskCategory;
}
public void net.customers.PersonCustomer.setOnlineRiskCategory(String onlineRiskCategory) {
OnlineRiskCategory = onlineRiskCategory;
}
public String net.customers.PersonCustomer.getPersonCommercialStatus() {
return PersonCommercialStatus;
}
public void net.customers.PersonCustomer.setPersonCommercialStatus(String personCommercialStatus) {
PersonCommercialStatus = personCommercialStatus;
}
#Around("execution(* net.xxx.xxx.xxx.DataMigration.populateMap(..))")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
Object arguments[] = joinPoint.getArgs();
if (arguments != null) {
HashMap<String, String> hMap = (HashMap) arguments[0];
PersonCustomer cus = (PersonCustomer) arguments[1];
return joinPoint.proceed();
}
If anyone has ideas please let me know.
regards,
FT
First suggestion, I would avoid mixing code-style aspectj with annotation-style. Ie- instead of #Around, use around.
Second, instead of getting the arguments from the joinPoint, you should bind them in the pointcut:
Object around(Map map, PersonCustomer cust) :
execution(* net.xxx.xxx.xxx.DataMigration.populateMap(Map, PersonCustomer) && args(map, cust) {
...
return proceed(map, cust);
}
Now, to answer your question: you also need to use intertype declarations to add new fields to your class, so do something like this:
private String net.customers.PersonCustomer.OfflineRiskCategory;
private String net.customers.PersonCustomer.OnlineRiskCategory;
private String net.customers.PersonCustomer.PersonCommercialStatus;
Note that the private keyword here means private to the aspect, not to the class that you declare it on.

Fluent NHibernate not querying the database correctly

i have just looked into hooking my application into nhibernate (fluent nhibernate) but i am having a few difficulties...
I have tried to follow what people have done and found this:
public class NHibernateSessionPerRequest : IHttpModule
{
private static readonly ISessionFactory _sessionFactory;
static NHibernateSessionPerRequest()
{
_sessionFactory = CreateSessionFactory();
}
public void Init(HttpApplication context)
{
context.BeginRequest += BeginRequest;
context.EndRequest += EndRequest;
}
public static ISession GetCurrentSession()
{
return _sessionFactory.GetCurrentSession();
}
public void Dispose() { }
private static void BeginRequest(object sender, EventArgs e)
{
ISession session = _sessionFactory.OpenSession();
session.BeginTransaction();
CurrentSessionContext.Bind(session);
}
private static void EndRequest(object sender, EventArgs e)
{
ISession session = CurrentSessionContext.Unbind(_sessionFactory);
if (session == null) return;
try
{
session.Transaction.Commit();
}
catch (Exception)
{
session.Transaction.Rollback();
}
finally
{
session.Close();
session.Dispose();
}
}
private static ISessionFactory CreateSessionFactory()
{
string connString = "AV8MediaUser";
FluentConfiguration configuration = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ShowSql().ConnectionString(
x => x.FromConnectionStringWithKey(connString)))
.ExposeConfiguration(
c => c.SetProperty("current_session_context_class", "web"))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Category>());
return configuration.BuildSessionFactory();
}
}
But when i run it through it seems to connect to the database correctly but it doesnt run a query:
return Session.CreateCriteria<Category>()
.List<Category>();
Am i doing something stupidly wrong?
CreateCriteria expects you to specify a model object name that you'd like to retrieve instances of. You seem to be missing your model object type name. Try something more like this:
List<YourModelObject> results = session.CreateCriteria<YourModelObject>()
.List<YourModelObject>();
To see what's actually being sent to the database consider using Ayende's NHProfiler - it will come in handy later when seeing what your more complex criteria queries or HQL queries actually result in...
Got it... i didnt realise that my mappings werent included in the project for some unknown reason... but included them again and it is all good!
Weird how it didnt throw an error though.