SonarQube Java rule for checking debug/trace logging level - java

I'm trying to write a customized java rule to check if the debug/trace log levels are enabled. If the log level check has been forgotten, the rule should report an issue.
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
public class CheckDebugAndTraceLevel {
private static final Log LOG = LogFactory.getLog(CheckDebugAndTraceLevel.class);
void foo()
{
if(LOG.isDebugEnabled())
{
LOG.debug("some debug text..");
}
LOG.debug("some debug text.."); // Noncompliant {{ check LOG.debug with an if statement}}
if(LOG.isTraceEnabled())
{
LOG.trace("some debug text..");
}
LOG.trace("some text.."); // Noncompliant {{ check LOG.trace with an if statement}}
}
}
I tested my rule with loggers and recieved "Log.debug" and "Log.trace" from my example class. Still, I get an assertion error while executing jUnit test.
public class DebugAndTraceRule extends BaseTreeVisitor implements JavaFileScanner {
private JavaFileScannerContext context;
private boolean logFlag = false;
#Override
public void scanFile(JavaFileScannerContext context) {
this.context = context;
scan(context.getTree());
}
#Override
public void visitMethod(MethodTree tree) {
super.visitMethod(tree);
String logOption;
for (StatementTree statement : tree.block().body()) {
if (statement.is(Kind.EXPRESSION_STATEMENT)) {
logOption = statement.firstToken().text() + ".";
//System.out.println(statement);
ExpressionStatementTreeImpl eStatement = (ExpressionStatementTreeImpl) statement;
MethodInvocationTreeImpl methodInvoc = (MethodInvocationTreeImpl) eStatement.expression();
MemberSelectExpressionTreeImpl memberSel = (MemberSelectExpressionTreeImpl) methodInvoc.methodSelect();
logOption += memberSel.identifier();
// check logOption
if (logFlag && (logOption.equals("LOG.debug") || logOption.equals("LOG.trace"))) {
//System.out.println(logOption + " - line:" + statement.firstToken().line());
context.reportIssue(this, tree, "debug/trace levels of your logger must be enabled!");
}
}
}
}
#Override
public void visitVariable(VariableTree tree) {
super.visitVariable(tree);
if (tree.type().symbolType().toString().equals("Log")) {
logFlag = true;
}
}
}
If someone could help me out, I would really appreciate it!

Related

How to programatically (java) prevent specific errors messages to be sent to Sentry

How to programatically (java) prevent specific errors messages to be sent to Sentry? I want, for example, do not send to Sentry errors with the word "any_example_word". It's important to know that filtering by error message is not enabled in the User Interface.
I'm using Sentry 1.7.23, but all examples I can find use latest version (4.*), which are tottaly different. They use classes and methods that do not exist in this old version.
I don't know if this is relevant, but my application runs over thorntail and it uses jdk 8.
Edit:
I'm trying to do this:
#WebListener
public class MyContextListener implements ServletContextListener {
private static SentryClient sentryClient = SentryClientFactory.sentryClient();
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
Sentry.init();
String testStrings = "ipsis litteris;some_error_message";
String[] messagesToIgnore = StringUtils.split(testStrings, ';');
sentryClient.addShouldSendEventCallback(new ShouldSendEventCallback() {
#Override
public boolean shouldSend(Event event) {
for (Map.Entry<String, SentryInterface> interfaceEntry : event.getSentryInterfaces().entrySet()) {
if (interfaceEntry.getValue() instanceof ExceptionInterface) {
ExceptionInterface i = (ExceptionInterface) interfaceEntry.getValue();
for (SentryException sentryException : i.getExceptions()) {
for (String msgToIgnore : messagesToIgnore) {
if (StringUtils.contains(sentryException.getExceptionMessage(), msgToIgnore)) {
return false;
}
}
}
}
}
return true;
}
});
Sentry.setStoredClient(sentryClient);
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
Question 1) Is this the correct place to initialize Sentry?
Question 2) Why ShouldSendEventCallback is lost? Looking at
io.sentry.SentryClient:
public void sendEvent(Event event) {
for (ShouldSendEventCallback shouldSendEventCallback : shouldSendEventCallbacks) {
if (!shouldSendEventCallback.shouldSend(event)) {
logger.trace("Not sending Event because of ShouldSendEventCallback: {}", shouldSendEventCallback);
return;
}
}
try {
connection.send(event);
} catch (LockedDownException | TooManyRequestsException e) {
logger.debug("Dropping an Event due to lockdown: " + event);
} catch (Exception e) {
logger.error("An exception occurred while sending the event to Sentry.", e);
} finally {
getContext().setLastEventId(event.getId());
}
}
In some point during app execution, sentryClient is reinitialized and shouldSendEventCallbacks becomes empty, what causes my messages not being filtered.
So I get back to question 1, since apparently sentry configuration is not being persistent.

How do I create a very simple rule using Apache Calcite and use it on Apache Flink?

I have this application in Flink which use Table API to print data from a source. THe official documentation of Flink says that the Table API uses Calcite on its core to translate and optimize query plans. They don't describe it very in deep, so I went to the source code and tried to copy some codes from there. But, as far as I saw, they use Calcite rules as well.
What if I want to implement my own rule? Is it possible? How do I implement a simple rule in Calcite to change the parameter of a filter for example?
Here is my code
public class HelloWorldCalcitePlanTableAPI {
private static final Logger logger = LoggerFactory.getLogger(HelloWorldCalcitePlanTableAPI.class);
private static final String TICKETS_STATION_01_PLATFORM_01 = "TicketsStation01Plat01";
public static void main(String[] args) throws Exception {
new HelloWorldCalcitePlanTableAPI("127.0.0.1", "127.0.0.1");
}
public HelloWorldCalcitePlanTableAPI(String ipAddressSource01, String ipAddressSink) throws Exception {
// Start streaming from fake data source sensors
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
// StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env, tableConfig);
StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);
// Calcite configuration file to change the query execution plan
// CalciteConfig cc = tableEnv.getConfig().getCalciteConfig();
CalciteConfig cc = new CalciteConfigBuilder()
.addNormRuleSet(RuleSets.ofList(MyFilterReduceExpressionRule.FILTER_INSTANCE))
.replaceDecoRuleSet(RuleSets.ofList(MyDataStreamRule.INSTANCE))
.build();
tableEnv.getConfig().setCalciteConfig(cc);
// obtain query configuration from TableEnvironment
StreamQueryConfig qConfig = tableEnv.queryConfig();
qConfig.withIdleStateRetentionTime(Time.minutes(30), Time.hours(2));
// Register Data Source Stream tables in the table environment
tableEnv.registerTableSource(TICKETS_STATION_01_PLATFORM_01,
new MqttSensorTableSource(ipAddressSource01, TOPIC_STATION_01_PLAT_01_TICKETS));
Table result = tableEnv.scan(TICKETS_STATION_01_PLATFORM_01)
.filter(VALUE + " >= 50 && " + VALUE + " <= 100 && " + VALUE + " >= 50")
;
tableEnv.toAppendStream(result, Row.class).print();
System.out.println("Execution plan ........................ ");
System.out.println(env.getExecutionPlan());
System.out.println("Plan explaination ........................ ");
System.out.println(tableEnv.explain(result));
System.out.println("........................ ");
System.out.println("NormRuleSet: " + cc.getNormRuleSet().isDefined());
System.out.println("LogicalOptRuleSet: " + cc.getLogicalOptRuleSet().isDefined());
System.out.println("PhysicalOptRuleSet: " + cc.getPhysicalOptRuleSet().isDefined());
System.out.println("DecoRuleSet: " + cc.getDecoRuleSet().isDefined());
// #formatter:on
env.execute("HelloWorldCalcitePlanTableAPI");
}
}
public class MyDataStreamRule extends RelOptRule {
public static final MyDataStreamRule INSTANCE = new MyDataStreamRule(operand(DataStreamRel.class, none()), "MyDataStreamRule");
public MyDataStreamRule(RelOptRuleOperand operand, String description) {
super(operand, "MyDataStreamRule:" + description);
}
public MyDataStreamRule(RelBuilderFactory relBuilderFactory) {
super(operand(DataStreamRel.class, any()), relBuilderFactory, null);
}
public void onMatch(RelOptRuleCall call) {
DataStreamRel dataStreamRel = (DataStreamRel) call.rel(0);
System.out.println("======================= MyDataStreamRule.onMatch ====================");
}
}
public class MyFilterReduceExpressionRule extends RelOptRule {
public static final MyFilterReduceExpressionRule FILTER_INSTANCE = new MyFilterReduceExpressionRule(
operand(LogicalFilter.class, none()), "MyFilterReduceExpressionRule");
public MyFilterReduceExpressionRule(RelOptRuleOperand operand, String description) {
super(operand, "MyFilterReduceExpressionRule:" + description);
}
public MyFilterReduceExpressionRule(RelBuilderFactory relBuilderFactory) {
super(operand(LogicalFilter.class, any()), relBuilderFactory, null);
}
public MyFilterReduceExpressionRule(RelOptRuleOperand operand) {
super(operand);
}
#Override
public void onMatch(RelOptRuleCall arg0) {
System.out.println("======================= MyFilterReduceExpressionRule.onMatch ====================");
}
}

Not able to load application.conf from cron job in play framework 2.4

I have created a cron job that start during application restart but when i tried to create db connection i am geeting null pointer exception. I am able to create and use db from other module using same configuration.
Below is my Application.conf
db.abc.driver=com.mysql.jdbc.Driver
db.abc.url="jdbc:mysql://localhost:3306/db_name?useSSL=false"
db.abc.username=root
db.abc.password=""
db.abc.autocommit=false
db.abc.isolation=READ_COMMITTED
And code that tried to access db is
public class SchduleJob extends AbstractModule{
#Override
protected void configure() {
bind(JobOne.class)
.to(JobOneImpl.class)
.asEagerSingleton();
} }
#ImplementedBy(JobOneImpl.class)
public interface JobOne {}
#Singleton
public class JobOneImpl implements JobOne {
final ActorSystem actorSystem = ActorSystem.create("name");
final ActorRef alertActor = actorSystem.actorOf(AlertActor.props);
public JobOneImpl() {
scheduleJobs();
}
private Cancellable scheduleJobs() {
return actorSystem.scheduler().schedule(
Duration.create(0, TimeUnit.MILLISECONDS), //Initial delay 0 milliseconds
Duration.create(6, TimeUnit.MINUTES), //Frequency 30 minutes
alertActor,
"alert",
actorSystem.dispatcher(),
null
);
}
}
public class AlertActor extends UntypedActor{
public static Props props = Props.create(AlertActor.class);
final ActorSystem actorSystem = ActorSystem.create("name");
final ActorRef messageActor = actorSystem.actorOf(MessageActor.props());
#Override
public void onReceive(Object message) throws Exception {
if(message != null && message instanceof String) {
RequestDAO requestDAO = new RequestDAO();
try {
List<DBRow> rows = requestDAO.getAllRow();
} catch(Exception exception) {
exception.printStackTrace();
}
}
}
}
public class RequestDAO {
public List<DBRow> getAllRow() throws Exception {
List<DBRow> rows = new ArrayList<DBRow>();
Connection connection = null;
try {
connection = DB.getDataSource("abc").getConnection();
connection.setAutoCommit(false);
} catch(Exception exception) {
exception.printStackTrace();
if(connection != null) {
connection.rollback();
} else {
System.out.println("in else***********");
}
return null;
} finally {
if(connection != null)
connection.close();
}
return schools;
}
When i am calling method getAllRow() of RequestDAO class it's throwing
java.lang.NullPointerException
at play.api.Application$$anonfun$instanceCache$1.apply(Application.scala:235)
at play.api.Application$$anonfun$instanceCache$1.apply(Application.scala:235)
at play.utils.InlineCache.fresh(InlineCache.scala:69)
at play.utils.InlineCache.apply(InlineCache.scala:55)
at play.api.db.DB$.db(DB.scala:22)
at play.api.db.DB$.getDataSource(DB.scala:41)
at play.api.db.DB.getDataSource(DB.scala)
at play.db.DB.getDataSource(DB.java:33)
But same code is working without cron job. What should i do to remove this error
Play uses the Typesafe config library for configuration.
I suspect your current working directory from the cron script isn't set, so it's probably not finding your application.conf (application.properties) file.
However, Config is nice in that it allows you to specify where to look for the file, either by its base name (to choose among .conf | .properties | .json extensions) or the filename including the extension on the java command line:
To specify the base name, use -Dconfig.resource=/path/to/application
To specify the full name, use -Dconfig.file=/path/to/application.properties

Optaplanner custom MoveFactory not being used

i'm in the process of reviving my optaplanner code that i wrote about 6 months ago and while trying to figure out why some of my hard constraints are being broken i found that a filter that i wrote that is supposed to filter out illegal moves is not being referred to. I put breakpoints at all of the methods of the move factory, the moves methods, and the filter and none are being called. I'm pretty sure that that wasn'nt the case before i updated to the latest version but i might be wrong.
Update: the factory is being used when i run optaplanner in my test case but not in production, so i guess this is not to due with my configuration but rather the scenario, but i don't know what may affect it being used or not
my solver config:
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<environmentMode>FULL_ASSERT</environmentMode>
<!-- Domain model configuration -->
<solutionClass>com.rdthree.plenty.services.activities.planner.ActivitySolution</solutionClass>
<entityClass>com.rdthree.plenty.services.activities.helpers.dtos.TaskPlannerDto</entityClass>
<entityClass>com.rdthree.plenty.services.activities.helpers.dtos.TaskResourceAllocationPlannerDto</entityClass>
<!-- Score configuration -->
<scoreDirectorFactory>
<scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
<scoreDrl>com/rdthree/plenty/services/activities/planner/activity-scoring.drl</scoreDrl>
<initializingScoreTrend>ONLY_DOWN</initializingScoreTrend>
</scoreDirectorFactory>
<!-- Optimization algorithms configuration -->
<termination>
<terminationCompositionStyle>OR</terminationCompositionStyle>
<bestScoreLimit>0hard/0soft</bestScoreLimit>
<secondsSpentLimit>60</secondsSpentLimit>
</termination>
<constructionHeuristic>
<queuedEntityPlacer>
<entitySelector id="resourceAllocationSelector">
<entityClass>com.rdthree.plenty.services.activities.helpers.dtos.TaskResourceAllocationPlannerDto</entityClass>
<cacheType>PHASE</cacheType>
<selectionOrder>SORTED</selectionOrder>
<sorterManner>DECREASING_DIFFICULTY_IF_AVAILABLE</sorterManner>
</entitySelector>
<changeMoveSelector>
<entitySelector mimicSelectorRef="resourceAllocationSelector" />
<valueSelector>
<variableName>resource</variableName>
<cacheType>PHASE</cacheType>
</valueSelector>
</changeMoveSelector>
</queuedEntityPlacer>
</constructionHeuristic>
<constructionHeuristic>
<queuedEntityPlacer>
<entitySelector id="taskSelector">
<entityClass>com.rdthree.plenty.services.activities.helpers.dtos.TaskPlannerDto</entityClass>
<cacheType>PHASE</cacheType>
<selectionOrder>SORTED</selectionOrder>
<sorterManner>DECREASING_DIFFICULTY_IF_AVAILABLE</sorterManner>
</entitySelector>
<changeMoveSelector>
<entitySelector mimicSelectorRef="taskSelector" />
<filterClass>com.rdthree.plenty.services.activities.planner.filters.TaskLengthChnageFilter</filterClass>
<valueSelector>
<variableName>interval</variableName>
<cacheType>PHASE</cacheType>
</valueSelector>
</changeMoveSelector>
</queuedEntityPlacer>
</constructionHeuristic>
<localSearch>
<unionMoveSelector>
<moveListFactory>
<moveListFactoryClass>com.rdthree.plenty.services.activities.planner.MoveResourceAllocationMoveFactory</moveListFactoryClass>
</moveListFactory>
<changeMoveSelector>
<fixedProbabilityWeight>1.0</fixedProbabilityWeight>
<filterClass>com.rdthree.plenty.services.activities.planner.filters.TaskLengthChnageFilter</filterClass>
<entitySelector id="taskMoveSelector">
<entityClass>com.rdthree.plenty.services.activities.helpers.dtos.TaskPlannerDto</entityClass>
</entitySelector>
<valueSelector>
<variableName>interval</variableName>
</valueSelector>
</changeMoveSelector>
</unionMoveSelector>
<acceptor>
<valueTabuSize>7</valueTabuSize>
</acceptor>
<forager>
<acceptedCountLimit>2000</acceptedCountLimit>
</forager>
</localSearch>
my custom move factory:
public class MoveResourceAllocationMoveFactory implements MoveListFactory<ActivitySolution> {
#Override
public List<? extends Move> createMoveList(ActivitySolution solution) {
List<Move> moveList = new ArrayList<Move>();
for (TaskResourceAllocationPlannerDto allocation : solution.getResourceAllocations()) {
for (TaskResourcePlannerDto resource : solution.getResources()) {
moveList.add(new MoveResourceAllocations(allocation, resource));
}
}
return moveList;
}
}
my custom move:
public class MoveResourceAllocations extends AbstractMove {
private TaskResourceAllocationPlannerDto allocation;
private TaskResourcePlannerDto newResource;
#Getter
#Setter
boolean doMove;
public MoveResourceAllocations(TaskResourceAllocationPlannerDto allocation, TaskResourcePlannerDto newResource) {
super();
this.allocation = allocation;
this.newResource = newResource;
}
#Override
public boolean isMoveDoable(ScoreDirector scoreDirector) {
if (allocation.getResource().equals(newResource)) {
return false;
}
return new ResourceTypeMismatchFilter().acceptCustomMove(scoreDirector, this);
}
#Override
public Move createUndoMove(ScoreDirector scoreDirector) {
return new MoveResourceAllocations(allocation, allocation.getResource());
}
#Override
public void doMoveOnGenuineVariables(ScoreDirector scoreDirector) {
scoreDirector.beforeVariableChanged(allocation, "resource");
updateOnHandAmounts(scoreDirector);
allocation.setResource(newResource);
scoreDirector.afterVariableChanged(allocation, "resource");
}
private void updateOnHandAmounts(ScoreDirector scoreDirector) {
ActivitySolution solution = (ActivitySolution) scoreDirector.getWorkingSolution();
List<OnHandForProduct> onHandForProducts = solution.getOnHandForProducts();
List<ProductInventoryTransactionPlannerDto> transactions = solution.getTransactions();
boolean transactionFoundForTask = false;
if ((newResource.getClass().getSimpleName().contains(Product.class.getSimpleName()))
&& allocation.getResourceClass().equals(Product.class)) {
// find the transaction caused by the task and product in question and replace the product in the
// transaction with the newly assigned product and revert this for an undo move
for (ProductInventoryTransactionPlannerDto transaction : transactions) {
if (transaction.getCauseId().equals(allocation.getTaskId())
&& transaction.getProductId() == (allocation.getResource().getId())
&& transaction.getTransactionTypeName().equals(InventoryTransactionType.SUBTRACT)) {
transaction.setProductId(newResource.getId());
transactionFoundForTask = true;
break;
}
}
if (!transactionFoundForTask) {
throw new EmptyResultDataAccessException(
"Internal scheduler fail: no product transaction found for the product-requiring task with id: "
+ allocation.getTaskId() + " for product : " + allocation.getResource(), 1);
}
TaskPlannerDto thisTask = null;
for (TaskPlannerDto task : solution.getTasks()) {
if (task.getId().equals(allocation.getTaskId())) {
thisTask = task;
}
}
Long oldProductId = allocation.getResource().getId();
Long newProductId = newResource.getId();
for (OnHandForProduct onHandForProduct : onHandForProducts) {
if (onHandForProduct.getProductId().equals(oldProductId)
&& onHandForProduct.getDate().isAfter(
thisTask.getInterval().getStart().withTimeAtStartOfDay()
.plusDays(0/* - GeneralPrefs.PRODUCT_PRESENCE_SAFETY_BUFFER*/))) {
onHandForProduct.setAmount(onHandForProduct.getAmount() + allocation.getAmount());
}
if (onHandForProduct.getProductId().equals(newProductId)
&& onHandForProduct.getDate().isAfter(
thisTask.getInterval().getStart().withTimeAtStartOfDay()
.plusDays(0/* - GeneralPrefs.PRODUCT_PRESENCE_SAFETY_BUFFER*/))) {
onHandForProduct.setAmount(onHandForProduct.getAmount() - allocation.getAmount());
}
}
}
}
#Override
public Collection<? extends Object> getPlanningEntities() {
return Collections.singletonList(allocation);
}
#Override
public Collection<? extends Object> getPlanningValues() {
return Collections.singletonList(newResource);
}
#Override
public String toString() {
return "replacing resource " + allocation.getResource() + " for task with id " + allocation.getId() + " with "
+ newResource;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((allocation == null) ? 0 : allocation.hashCode());
result = prime * result + ((newResource == null) ? 0 : newResource.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MoveResourceAllocations other = (MoveResourceAllocations) obj;
if (allocation == null) {
if (other.allocation != null)
return false;
} else if (!allocation.equals(other.allocation))
return false;
if (newResource == null) {
if (other.newResource != null)
return false;
} else if (!newResource.equals(other.newResource))
return false;
return true;
}
}
The config looks good.
1) Maybe the 2 Construction Heuristics phase never completely finish.
Turn on INFO logging (or better yet DEBUG). It will log when each of the 2 Construction Heuristics ends.
2) Maybe Local Search starts with a ChangeMoveSelector (it's a union, so any one of the 2 selectors can go first), and it hangs somehow in the filter. Turn on TRACE logging to see the selected moves.

Wicket image component not found on page

I get the following problem when trying to display a list of items. For each item, I have to display an image which is dynamically loaded via a Wicket WebResource. The items are loaded step by step — 50 at a time — upon user scrolling, using an Ajax scroll.
[ERROR] 2011-04-19 09:58:18,000 btpool0-1 org.apache.wicket.RequestCycle.logRuntimeException (host=, request=, site=):
org.apache.wicket.WicketRuntimeException: component documentList:scroller:batchElem:666:content:item:3:batchItemContent:linkToPreview:imageThumbnail not found on page com.webapp.document.pages.DocumentListPage[id = 1]
listener interface = [RequestListenerInterface name=IResourceListener, method=public abstract void org.apache.wicket.IResourceListener.onResourceRequested()]
org.apache.wicket.protocol.http.request.InvalidUrlException: org.apache.wicket.WicketRuntimeException: component documentList:scroller:batchElem:666:content:item:3:batchItemContent:linkToPreview:imageThumbnail
not found on page com.webapp.document.pages.DocumentListPage[id = 1] listener interface = [RequestListenerInterface name=IResourceListener, method=public abstract void org.apache.wicket.IResourceListener.onResourceRequested()]
at org.apache.wicket.protocol.http.WebRequestCycleProcessor.resolve(WebRequestCycleProcessor.java:262)
at org.apache.wicket.RequestCycle.step(RequestCycle.java:1310)
at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1428)
at org.apache.wicket.RequestCycle.request(RequestCycle.java:545)
at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:479)
at org.apache.wicket.protocol.http.WicketFilter$$EnhancerByGuice$$51619816.CGLIB$doGet$6()
at org.apache.wicket.protocol.http.WicketFilter$$EnhancerByGuice$$51619816$$FastClassByGuice$$6d42bf5d.invoke()
at com.google.inject.internal.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:64)
at com.freiheit.monitoring.PerformanceMonitoringMethodInterceptor.invoke(PerformanceMonitoringMethodInterceptor.java:115)
at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:64)
at com.google.inject.internal.InterceptorStackCallback.intercept(InterceptorStackCallback.java:44)
at org.apache.wicket.protocol.http.WicketFilter$$EnhancerByGuice$$51619816.doGet()
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:312)
at org.apache.wicket.protocol.http.WicketFilter$$EnhancerByGuice$$51619816.CGLIB$doFilter$4()
How can this problem be solved?
Here is the part of the code responsible for adding the image:
previewLink.add(createThumbnailSmall("imageThumbnail", documentModel));
in
createThumbnailSmall(final String id, final IModel<BaseDocument> documentModel) {
// thumbnailResource is an object that contains the path of the image
if (thumbnailResource != null) {
final WebResource resource = getWebResource(thumbnailResource);
final Image image = new Image(id, resource);
return image;
}
return new InvisibleContainer(id);
}
WebResource getWebResource(final DocumentResource documentResource) {
return new WebResource() {
private static final long serialVersionUID = 1L;
#Override
public IResourceStream getResourceStream() {
return new BaseStreamResource(documentResource);
}
};
}
where BaseStreamResource is the following:
public class BaseStreamResource extends AbstractResourceStream {
private InputStream _fileInputStream = null;
private DocumentResource _resource = null;
public BaseStreamResource(final DocumentResource documentResource) {
_resource = documentResource;
}
#Override
public InputStream getInputStream() throws ResourceStreamNotFoundException {
if (_fileInputStream == null) {
try {
if (_resource == null) {
throw new ResourceStreamNotFoundException("Resource was null");
}
_fileInputStream = _resource.getFileInputStream();
} catch (final ResourceNotAvailableException ex) {
throw new ResourceStreamNotFoundException(ex);
}
}
return _fileInputStream;
}
In HTML:
<a wicket:id="linkToPreview" href="#">
<img wicket:id="imageThumbnail" alt="Attachment"></img></a>
The code added hasn't really added any clues for me, but maybe I can help narrow it down a bit anyway.
The stacktrace includes a reference to com.webapp.document.pages.DocumentListPage, which is likely calling some of the code you've posted. The error indicates a bad url, so debugging into that class, adding debug prints, and looking at the values of any field containing a url might be worthwhile.
It might even help to modify the code in DocumentListPage (maybe temporarily for debugging) to catch org.apache.wicket.protocol.http.request.InvalidUrlException and adding debugging prints specifically when the exception is caught.
This isn't really an answer, but it's too big for a comment, and maybe it'll help you get closer to an answer.
The following solution solved the problem:
- extend WebResource class
- add extended class as a resource to application shared resources
Ex:
public class MyWebResource extends WebResource {
final ValueMap map = new ValueMap();
#Override
public IResourceStream getResourceStream() {
String fileName = getFileName();
File file = new File(basePath, fileName);
if (!file.exists()) {
LOG.error("File does not exist: " + file);
throw new IllegalStateException("File does not exist: " + file);
}
return new FileResourceStream(file);
}
public final void addResource() {
Application.get().getSharedResources().add(getClass().getName(), this);
}
protected String getFileName() {
return getParameters().getString("id");
}
public final String urlFor(final String fileName) {
final ResourceReference resourceReference = new ResourceReference(getClass().getName());
final String encodedValue = WicketURLEncoder.QUERY_INSTANCE.encode(fileName);
map.add("id", encodedValue);
final CharSequence result = RequestCycle.get().urlFor(resourceReference, map);
if (result == null) {
throw new IllegalStateException("The resource was not added! "
+ "In your Application class add the following line:"
+ "MyConcreteResource.INSTANCE.addResource()");
}
String absoluteUrl = RequestUtils.toAbsolutePath(result.toString());
return absoluteUrl;
}
}
In Application class, in init(), I have added MyWebResource to shared resources:
public void init() {
...
new MyWebResource().addResource();
...
}

Categories