Provider org.togglz.slf4j.Slf4jLogProvider not a subtype - togglz

I have a library, built with Maven, that uses Spring 4.0.3.RELEASE and Togglz 2.2.0.Final. I'm trying to write a JUnit 4.11 test of my Spring class and running into the following error on the first test that gets executed:
testCreateItem_throwsItemServiceBusinessException(impl.ItemServiceImplTest) Time elapsed: 1.771 sec <<< ERROR!
java.util.ServiceConfigurationError: org.togglz.core.spi.LogProvider:
Provider org.togglz.slf4j.Slf4jLogProvider not a subtype
Here is the relevant java test snippet:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = AppConfig.class, loader = AnnotationConfigContextLoader.class)
#PrepareForTest({ ItemServiceImpl.class })
public class ItemServiceImplTest {
#Rule
public TogglzRule togglzRule = TogglzRule.allDisabled(Features.class);
#Rule
public PowerMockRule powerMockRule = new PowerMockRule();
#Test(expected = ItemServiceBusinessException.class)
public void testCreateItem_throwsItemServiceBusinessException() throws Exception {
PowerMockito.doReturn(mockMetricsData).when(serviceUnderTest, START_METRICS_METHOD_NAME, any(MetricsOperationName.class), any(RequestContext.class));
when(mockDao.createItem(any(Item.class), any(RequestContext.class))).thenThrow(dataBusinessException);
serviceUnderTest.createItem(item, context);
verify(mockItemServiceValidator).validate(any(Item.class), any(RequestContext.class));
PowerMockito.verifyPrivate(serviceUnderTest).invoke(START_METRICS_METHOD_NAME, any(MetricsOperationName.class), any(RequestContext.class));
verify(mockDao).createItem(any(Item.class), any(RequestContext.class));
}
}
Subsequent test calls get the following error:
java.lang.NoClassDefFoundError: Could not initialize class org.togglz.junit.TogglzRule
Here are some relevant dependencies I have:
org.mockito:mockito-all=org.mockito:mockito-all:jar:1.9.5:compile,
org.powermock:powermock-module-junit4=org.powermock:powermock-module-junit4:jar:1.5.6:test,org.powermock:powermock-module-junit4-common=org.powermock:powermock-module-junit4-common:jar:1.5.6:test,
org.powermock:powermock-reflect=org.powermock:powermock-reflect:jar:1.5.6:test,
org.powermock:powermock-api-mockito=org.powermock:powermock-api-mockito:jar:1.5.6:test,
org.powermock:powermock-api-support=org.powermock:powermock-api-support:jar:1.5.6:test,
org.powermock:powermock-module-junit4-rule=org.powermock:powermock-module-junit4-rule:jar:1.5.6:test,
org.powermock:powermock-classloading-base=org.powermock:powermock-classloading-base:jar:1.5.6:test,
org.powermock:powermock-core=org.powermock:powermock-core:jar:1.5.6:test,
org.powermock:powermock-classloading-xstream=org.powermock:powermock-classloading-xstream:jar:1.5.6:test,
org.togglz:togglz-core=org.togglz:togglz-core:jar:2.2.0.Final:compile,
org.togglz:togglz-slf4j=org.togglz:togglz-slf4j:jar:2.2.0.Final:compile,
org.togglz:togglz-spring-core=org.togglz:togglz-spring-core:jar:2.2.0.Final:compile,
org.togglz:togglz-testing=org.togglz:togglz-testing:jar:2.2.0.Final:test,
org.togglz:togglz-junit=org.togglz:togglz-junit:jar:2.2.0.Final:test
And I have provided a LogProvider (org.togglz.slf4j.Slf4jLogProvider) via SPI, located at META-INF/serivces/org.togglz.core.spi.LogProvider
This error is baffling as Slf4jLogProvider should be assignable from LogProvider. Sorry for the verbosity, but I wanted to try and show a complete picture. The code in class "under test" is making a call to see if a single feature is enabled inside the create method.

First of all: You don't need to configure the log provider in your application. Including togglz-slf4j on your application path is sufficient because this jar contains the corresponding SPI file.
Could you please check if there are multiple conflicting versions of the Togglz JAR files on your classpath? For example using togglz-core-2.2.0.Final.jar together with togglz-slf4j-2.1.0.Final.jar could result in an error like this.
This can happen if you update Togglz and your IDE didn't remove the old archives. Running a clean build and/or selecting "Update Maven Configuration" on Eclipse will fix this problem.

Related

JpaSagaStore in conjunction with Jackson unable to properly store state

In a SpringBoot application, I have the following configuration:
axon:
axonserver:
servers: "${AXON_SERVER:localhost}"
serializer:
general: jackson
messages: jackson
events: jackson
logging.level:
org.axonframework.modelling.saga: debug
Downsizing the scenario to bare minimum, the relevant portion of Saga class:
#Slf4j
#Saga
#ProcessingGroup("AuctionEventManager")
public class AuctionEventManagerSaga {
#Autowired
private transient EventScheduler eventScheduler;
private ScheduleToken scheduleToken;
private Instant auctionTimerStart;
#StartSaga
#SagaEventHandler(associationProperty = "auctionEventId")
protected void on(final AuctionEventScheduled event) {
this.auctionTimerStart = event.getTimerStart();
// Cancel any pre-existing previous job, since the scheduling thread might be lost upon a crash/restart of JVM.
if (this.scheduleToken != null) {
this.eventScheduler.cancelSchedule(this.scheduleToken);
}
this.scheduleToken = this.eventScheduler.schedule(
this.auctionTimerStart,
AuctionEventStarted.builder()
.auctionEventId(event.getAuctionEventId())
.build()
);
}
#EndSaga
#SagaEventHandler(associationProperty = "auctionEventId")
protected void on(final AuctionEventStarted event) {
log.info(
"[AuctionEventManagerSaga] Current state: {scheduleToken={}, auctionTimerStart={}}",
this.scheduleToken,
this.auctionTimerStart
);
}
}
In the final compiled class, we will end up having 4 properties: log (from #Slf4j), eventScheduler (transient, #Autowired), scheduleToken and auctionTimerStart.
For reference information, here is a sample of the general approach I've been using for both Command and Event classes:
#Value
#Builder
#JsonDeserialize(builder = AuctionEventStarted.AuctionEventStartedBuilder.class)
public class AuctionEventStarted {
AuctionEventId auctionEventId;
#JsonPOJOBuilder(withPrefix = "")
public static final class AuctionEventStartedBuilder {}
}
When executing the code, you get the following output:
2020-05-12 15:40:01.180 DEBUG 1 --- [mandProcessor-4] o.a.m.saga.repository.jpa.JpaSagaStore : Updating saga id c8aff7f7-d47f-4616-8a96-a40044cb7e3b as {}
As soon as the general serializer is changed to xstream, the content is serialized properly, but I face another issue during deserialization, since I have private static final class Builder classes using Lombok.
So is there a way for Axon to handle these scenarios:
1- Axon to safely manage Jackson to ignore #Autowired, transient and static properties from #Saga classes? I've attempted to manually define #JsonIgnore at non-state properties and it still didn't work.
2- Axon to safely configure XStream to ignore inner classes (mostly Builder classes implemented as private static final)?
Thanks in advance,
EDIT: I'm pursuing a resolution using my preferred serializer: JSON. I attempted to modify the saga class and extend JsonSerializer<AuctionEventManagerSaga>. For that I implemented the methods:
#Override
public Class<AuctionEventManagerSaga> handledType() {
return AuctionEventManagerSaga.class;
}
#Override
public void serialize(
final AuctionEventManagerSaga value,
final JsonGenerator gen,
final SerializerProvider serializers
) throws IOException {
gen.writeStartObject();
gen.writeObjectField("scheduleToken", value.eventScheduler);
gen.writeObjectField("auctionTimerStart", value.auctionTimerStart);
gen.writeEndObject();
}
Right now, I have something being serialized, but it has nothing to do with the properties I've defined:
2020-05-12 16:20:01.322 DEBUG 1 --- [mandProcessor-0] o.a.m.saga.repository.jpa.JpaSagaStore : Storing saga id c4b5d94c-7251-40a5-accf-332768b1cacd as {"delegatee":null,"unwrappingSerializer":false}
EDIT 2 Decided to add more insight into the issue I experience when I switch general to use XStream (even though it's somewhat unrelated to the main issue described in the title).
Here is the issue it complains to me:
2020-05-12 17:08:06.495 DEBUG 1 --- [ault-executor-0] o.a.a.c.command.AxonServerCommandBus : Received command response [message_identifier: "79631ffb-9a87-4224-bed3-a957730dced7"
error_code: "AXONIQ-4002"
error_message {
message: "No converter available\n---- Debugging information ----\nmessage : No converter available\ntype : jdk.internal.misc.InnocuousThread\nconverter : com.thoughtworks.xstream.converters.reflection.ReflectionConverter\nmessage[1] : Unable to make field private static final jdk.internal.misc.Unsafe jdk.internal.misc.InnocuousThread.UNSAFE accessible: module java.base does not \"opens jdk.internal.misc\" to unnamed module #7728643a\n-------------------------------"
location: "1#600b5b87a922"
details: "No converter available\n---- Debugging information ----\nmessage : No converter available\ntype : jdk.internal.misc.InnocuousThread\nconverter : com.thoughtworks.xstream.converters.reflection.ReflectionConverter\nmessage[1] : Unable to make field private static final jdk.internal.misc.Unsafe jdk.internal.misc.InnocuousThread.UNSAFE accessible: module java.base does not \"opens jdk.internal.misc\" to unnamed module #7728643a\n-------------------------------"
}
request_identifier: "2f7020b1-f655-4649-bbe0-d6f458b3c2f3"
]
2020-05-12 17:08:06.505 WARN 1 --- [ault-executor-0] o.a.c.gateway.DefaultCommandGateway : Command 'ACommandClassDispatchedFromSaga' resulted in org.axonframework.commandhandling.CommandExecutionException(No converter available
---- Debugging information ----
message : No converter available
type : jdk.internal.misc.InnocuousThread
converter : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
message[1] : Unable to make field private static final jdk.internal.misc.Unsafe jdk.internal.misc.InnocuousThread.UNSAFE accessible: module java.base does not "opens jdk.internal.misc" to unnamed module #7728643a
-------------------------------)
Still no luck on resolving this...
I've worked on Axon systems where the only used Serializer implementation was the JacksonSerializer too. Mind you though, this is not what the Axon team recommends. For messages (i.e. commands, events and queries) it makes perfect sense to use JSON as the serialized format. But switching the general Serializer to jackson means you have to litter your domain logic (e.g. your Saga) with Jackson specifics "to make it work".
Regardless, backtracking to my successful use case of jackson-serialized-sagas. In this case we used the correct match of JSON annotations on the fields we desired to take into account (the actual state) and to ignore the one's we didn't want deserialized (with either transient or #JsonIgnore). Why both do not seem to work in your scenario is not entirely clear at this stage.
What I do recall is that the referenced project's team very clearly decided against Lombok due to "overall weirdnes" when it comes to de-/serialization. As a trial it thus might be worth to not use any Lombok annotations/logic in the Saga class and see if you can de-/serialize it correctly in such a state.
If it does work at that moment, I think you have found your culprit for diving in further search.
I know this isn't an exact answer, but I hope it helps you regardless!
Might be worthwhile to share the repository where this problems occurs in; might make the problem clearer for others too.
I was able to resolve the issue #2 when using XStream as general serializer.
One of the Sagas had an #Autowired dependency property that was not transient.
XStream was throwing some cryptic message, but we managed to track the problem and address it.
As for JSON support, we had no luck. We ended up switched everything to XStream for now, as the company only uses Java and it would be ok to decode the events using XStream.
Not the greatest solution, as we really wanted (and hoped) JSON would be supported properly out of the box. Mind you, this is in conjunction with using Lombok which caused for the nuisance in this case.

Error resolving template with Spring Boot using Thymeleaf packaged in a .jar

I have a Spring Boot application using Thymeleaf as template resolver, which works fine when debugging from NetBeans, but gives me this error running its .jar:
Error resolving template "/theme/property", template might not exist or might not be accessible by any of the configured Template Resolvers
The app is set to auto-configurer with the annotation #SpringBootApplication, at an extension of SpringBootServletInitializer. I haven't set any contextPath into the properties file. I'm using Thymeleaf 2.1.6 and Spring 4 version. The jar is generated with Maven.
Doing some research I've come out that in some controllers I was passing a double slash, which I've solved but most pages still not working.
This controller works:
#GetMapping("/{idweb}")
String frontEndHome(#PathVariable("idweb")Integer idweb, Model model){
...
return "theme/home";
With the return statement set as return "/theme/home"; doesn't work. I guess, because the template resolver is recieving a double slash (//).
This other controller raises the error:
#GetMapping("/{idweb}/property")
String frontEndProperty(#PathVariable("idweb") Integer idweb, #RequestParam(value = "idproperty", required = false) Integer idproperty, Model model) throws Exception {
...
return "theme/property";
The index controller works fine as well:
#GetMapping("/")
public String index(Model model){
...
return "index";
}
That's my application starter class:
#SpringBootApplication
public class RentalWebsApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(RentalWebsApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(RentalWebsApplication.class, args);
}
}
For Thymeleaf I haven't set any configuration, although I've tested the app setting this into the application.properties file, with the same result:
spring.thymeleaf.prefix=classpath:/templates/
All html files are set into:
src/main/resources/templates
The html files from the examples are in:
src/main/resources/templates/index.html
src/main/resources/templates/theme/home.html
src/main/resources/templates/theme/property.html
There are some other questions dealing with the same issue, but none has a solution that works for me. Any help, would be much appreciated.
Update
Deploying the jar into Pivotal Web Services, the whole website works fine, but not deploying it with Boxfuse, Heroku or running the jar locally. Therefore, I guess the origin of the problem is some wrong configuration, that Pivotal system detects and corrects.*
*
PWS isn't correcting a configuration problem. It unpacks your jar file before running the application which stops the double slash from causing a problem. – Andy Wilkinson
At the end the solution was related to the double slashes, that the classpath:/templates/ gets if we set a return statement with a slash at the beginning like:
return "/theme/property"
Instead of:
return "theme/property"
In my case, the problem was not at the controller, but in the html with the Thymeleaf references of fragments, like in this example:
<footer th:replace="/index::footer"></footer>
Instead of:
<footer th:replace="index::footer"></footer>
What I don't understand is why the IDE's (NetBeans and STS), where not raising the error.
use
return new ModelAndView("member2",map);
instead of
return new ModelAndView("/member2",map);
Remove spring.thymeleaf.prefix=classpath:/templates/ from your application.properties.

Unit Test Project: "No connection string could be found in the application config file"

I had an existing MVC5 web app. I just created a new Unit Test Project and added the following code....
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SomethingApp.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SUT = SomethingApp.Services.ReportingServices; // SUT = System Under Test
namespace SomethingApp.Services.Tests
{
[TestClass]
public class GettingScoreForQuestionShould
{
[TestMethod]
public void ReturnScoreWhenGivenValidData()
{
// Arrange
int eventId = 39;
int questionId = 271;
decimal score;
// Act
score = SUT.GetScoreForQuestion(eventId, questionId);
// Assert
Assert.AreEqual("80",score);
}
}
}
When the method GetScoreForQuestion runs in the normal web app it runs perfect. But, when I run it through the test method I'm getting this error...
Message: Test method SomethingApp.Services.Tests.GettingScoreForQuestionShould.ReturnScoreWhenGivenValidData
threw exception: System.InvalidOperationException: No connection string
named 'myDbContext' could be found in the application config file.
The error is, of course, coming from the method GetScoreForQuestion, which works fine in the normal web app.
I don't understand why I need to add an application config file and this config connection string to the test project. Seems like, since I'm calling the method in the MVC project, that this has the responsibility of making the connection and doing it's thing (which it's doing in the normal course of the app). Am I mistaking something?
And, I tried adding a new application.config file and the connection string to the unit test project, but then the test method won't show up anymore in the Test Explorer after build. Any suggestions? Thanks!
UPDATE ****
Here's the code for GetScoreForQuestion (the offending method, which works in the web app fine, but not when called thru the test method)....
public static decimal GetScoreForQuestion(int eventId, int ThingyQuestionId)
{
// the following line fails with the connection issue
var ThingyResults = Db.ThingyResults.Where(e => e.EventId == eventId && e.ThingyQuestionId == ThingyQuestionId)
.AsNoTracking().ToList();
:
:
:
}
Db is declared in the same class as...
public static class ReportingServices
{
private static readonly ThingyContext Db = new ThingyContext();
When you are executing a unittest, that project is your running application. So that is where the configuration file is read from. And note that you need an app.config, not a web.config.
It looks like you may be creating a new ThingyContext within your ReportingServices class. Look into injecting an Interface so that you can substitute a mock implementation for testing purposes.
Here's some links to help get you started:
https://romiller.com/2012/02/14/testing-with-a-fake-dbcontext/
https://ardalis.com/new-is-glue

Configuring Logback: report time from application start instead of current date/time

During troubleshooting in development environment I would like to have time from application start instead of current date/time in logs.
Like in dmesg output.
What configuration and formatter I should use?
UPDATE There is an example from official site: https://logback.qos.ch/manual/layouts.html#writingYourOwnLayout where custom layout is implemented:
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.LayoutBase;
public class MySampleLayout extends LayoutBase<ILoggingEvent> {
public String doLayout(ILoggingEvent event) {
StringBuffer sbuf = new StringBuffer(128);
sbuf.append(event.getTimeStamp() - event.getLoggingContextVO.getBirthTime());
sbuf.append(" ");
sbuf.append(event.getLevel());
return sbuf.toString();
}
}
For me it's over complicated. Such simple thing shouldn't require compilation but rather configuration... Why I need to repackage jar or extend CLASSPATH to include custom written writer?
Seems that official docs has notes on this:
r / relative Outputs the number of milliseconds elapsed since the start
of the application until the creation of the logging event.
But you can't format it as date:
<encoder>
<pattern>%r %5p [%15.15t] %logger%n%m%wEx%n</pattern>
</encoder>

Launch Java from JRuby script throws TypeError: no public constructors for Java

I have a Java application that I am trying to launch from a JRuby script. I've been googling/t-shooting/iterating through so many solutions - my "basic" script is:
include Java
require 'c:/nm/bin/h4j.jar'
module HOLTER
include_package 'com.nemon.h4j.H4JFrame';
end
include_class Java::ComNemonH4j::H4JFrame
H4JFrame.new
This throws the following error:
TypeError: no public constructors for Java::ComNemonH4j::H4JFrame
(root) at h4j_initialTest.rb:7
And I've found that this also throws the same error:
$nm = HOLTER::H4JFrame.new
The main constructor for my application is:
public static void main(String argv[])
{
captureOutput();
new H4JFrame(argv);
}
So what do I need to do to have my script simply launch my application? Any/all advice and pointers would be GREATLY appreciated!!
Does H4JFrame have a 0 argument constructor? In your java main you show it being called with String argv[] as the argument, so I would assume it does not. To start your application with your current code, you would need to pass a Java String array to H4JFrame.
include Java
require 'c:/nm/bin/h4j.jar'
module HOLTER
include_package 'com.nemon.h4j.H4JFrame';
end
include_class Java::ComNemonH4j::H4JFrame
str_arr = ["example input", "this is an array of strings", "it is a ruby object"]
H4JFrame.new(str_arr.to_java :String)

Resources