I'm running my tests using gradle testFlavorType
JSONObject jsonObject1 = new JSONObject();
JSONObject jsonObject2 = new JSONObject();
jsonObject1.put("test", "test");
jsonObject2.put("test", "test");
assertEquals(jsonObject1.get("test"), jsonObject2.get("test"));
The above test succeeds.
jsonObject = new SlackMessageRequest(channel, message).buildBody();
String channelAssertion = jsonObject.getString(SlackMessageRequest.JSON_KEY_CHANNEL);
String messageAssertion = jsonObject.getString(SlackMessageRequest.JSON_KEY_TEXT);
assertEquals(channel, channelAssertion);
assertEquals(message, messageAssertion);
But the above two requests fail. The stack trace says that channelAssertion and messageAssertion are null, but not sure why. My question is: Why are the above two asserts failing?
Below is the SlackMessageRequest.
public class SlackMessageRequest
extends BaseRequest {
// region Variables
public static final String JSON_KEY_TEXT = "text";
public static final String JSON_KEY_CHANNEL = "channel";
private String mChannel;
private String mMessage;
// endregion
// region Constructors
public SlackMessageRequest(String channel, String message) {
mChannel = channel;
mMessage = message;
}
// endregion
// region Methods
#Override
public MethodType getMethodType() {
return MethodType.POST;
}
#Override
public JSONObject buildBody() throws JSONException {
JSONObject body = new JSONObject();
body.put(JSON_KEY_TEXT, getMessage());
body.put(JSON_KEY_CHANNEL, getChannel());
return body;
}
#Override
public String getUrl() {
return "http://localhost:1337";
}
public String getMessage() {
return mMessage;
}
public String getChannel() {
return mChannel;
}
// endregion
}
Below is the stacktrace:
junit.framework.ComparisonFailure: expected:<#tk> but was:<null>
at junit.framework.Assert.assertEquals(Assert.java:100)
at junit.framework.Assert.assertEquals(Assert.java:107)
at junit.framework.TestCase.assertEquals(TestCase.java:269)
at com.example.app.http.request.SlackMessageRequestTest.testBuildBody(SlackMessageRequestTest.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at junit.framework.TestCase.runTest(TestCase.java:176)
at junit.framework.TestCase.runBare(TestCase.java:141)
at junit.framework.TestResult$1.protect(TestResult.java:122)
at junit.framework.TestResult.runProtected(TestResult.java:142)
at junit.framework.TestResult.run(TestResult.java:125)
at junit.framework.TestCase.run(TestCase.java:129)
at junit.framework.TestSuite.runTest(TestSuite.java:252)
at junit.framework.TestSuite.run(TestSuite.java:247)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:49)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:64)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:360)
at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
EDIT 5:55PM EST
I've figured out that I can log with System.out.println("") and then see the results by running gradle testFlavorType --debug and by trial and error I've discovered the following weird situation:
#Override
public JSONObject buildBody() throws JSONException {
System.out.println("buildBody mChannel = " + mChannel);
System.out.println("buildBody mMessage = " + mMessage);
JSONObject body = new JSONObject();
body.put(JSON_KEY_TEXT, getMessage());
body.put(JSON_KEY_CHANNEL, getChannel());
if (body.length() != 0) {
Iterator<String> keys = body.keys();
if (keys.hasNext()) {
do {
String key = keys.next();
System.out.println("keys: " + key);
} while (keys.hasNext());
}
} else {
System.out.println("There are no keys????");
}
return body;
}
For some reason, "There are no keys????" is printing out?!?!?!?! Why?!
EDIT 6:20PM EST
I've figured out how to debug unit tests. According to the debugger, the assigned JSONObject is returning "null". I have no clue what this means (see below). Since I think this is relevant, my gradle file includes the following:
testOptions {
unitTests.returnDefaultValues = true
}
It's especially strange because if I construct a JSONObject inside the test, then everything works fine. But if it is part of the original application's code, then it doesn't work and does the above.
As Lucas says, JSON is bundled up with the Android SDK, so you are working with a stub.
The current solution is to pull JSON from Maven Central like this:
dependencies {
...
testImplementation 'org.json:json:20210307'
}
You can replace the version 20210307 with the the latest one depending on the Android API. It is not known which version of the maven artefact corresponds exactly/most closely to what ships with Android.
Alternatively, you can download and include the jar:
dependencies {
...
testImplementation files('libs/json.jar')
}
Note that you also need to use Android Studio 1.1 or higher and at least build tools version 22.0.0 or above for this to work.
Related issue: #179461
The class JSONObject is part of the android SDK. That means that is not available for unit testing by default.
From http://tools.android.com/tech-docs/unit-testing-support
The android.jar file that is used to run unit tests does not contain
any actual code - that is provided by the Android system image on real
devices. Instead, all methods throw exceptions (by default). This is
to make sure your unit tests only test your code and do not depend on
any particular behaviour of the Android platform (that you have not
explicitly mocked e.g. using Mockito).
When you set the test options to
testOptions {
unitTests.returnDefaultValues = true
}
you are fixing the "Method ... not mocked." problem, but the outcome is that when your code uses new JSONObject() you are not using the real method, you are using a mock method that doesn't do anything, it just returns a default value. That's the reason the object is null.
You can find different ways of solving the problem in this question: Android methods are not mocked when using Mockito
Well, my first hunch would be that your getMessage() method returns null. You could show the body of that method in your question and have us find the answer for you, but you should probably research how to debug android applications using breakpoints.
That way you can run your code step by step and see the values of each variable at every step. That would show you your problem in no time, and it's a skill you should definitely master as soon as possible if you intend to get seriously involved in programming.
Related
I am using OWLAPI to get all the inferred axioms and their explanations, for some ontologies. For the explanations, I need to get the explanation with the minimal set of axioms for each inferred axiom (laconic explanation), but I can't figure out how to do it, and I don't see any mention of laconic in the owlapi docs (http://owlcs.github.io/owlapi/apidocs_5/index.html).
Is there a way to get the laconic explanations for an inferred axiom in OWLAPI?
If so, is it possible to give me an example of how I can achieve this?
UPDATE: Following the advice given in comments, I changed my code to:
public static void explain(OWLAxiom entailment, ExplanationGenerator<OWLAxiom> explanation_generator) {
try {
Set<Explanation<OWLAxiom>> explanations =
explanation_generator.getExplanations(entailment, 1);
explanations.forEach(System.out::println);
System.out.println("EndOfExplanation\n");
} catch (Exception e) {
System.out.println(e);
}
};
// This method replicates code existing in the owlexplanation project;
// it's needed because the factories in owlexplanation do not set InitialEntailmentCheckStrategy correctly
public static ExplanationGeneratorFactory<OWLAxiom> createExplanationGeneratorFactory(
OWLReasonerFactory reasonerFactory, ExplanationProgressMonitor<OWLAxiom> progressMonitor,
Supplier<OWLOntologyManager> m) {
EntailmentCheckerFactory<OWLAxiom> checker = new SatisfiabilityEntailmentCheckerFactory(reasonerFactory, m);
Configuration<OWLAxiom> config = new Configuration<>(checker,
new StructuralTypePriorityExpansionStrategy<OWLAxiom>(InitialEntailmentCheckStrategy.PERFORM, m),
new DivideAndConquerContractionStrategy<OWLAxiom>(), progressMonitor, m);
return new BlackBoxExplanationGeneratorFactory<>(config);
};
public static void main(String[] args) {
...
ExplanationGeneratorFactory<OWLAxiom> genFac =
ExplanationManager.createLaconicExplanationGeneratorFactory(
reasoner_factory, OWLManager::createOWLOntologyManager);
ExplanationGenerator<OWLAxiom> gen = genFac.createExplanationGenerator(onto);
inferred_axioms_onto.logicalAxioms().forEach(e -> explain(e, gen));
}
but I still get java.lang.NullPointerException which is caused in the line Set<Explanation<OWLAxiom>> explanations = explanation_generator.getExplanations(entailment, 1);.
The error stack trace is:
at org.semanticweb.owl.explanation.impl.blackbox.StructuralTypePriorityExpansionStrategy.doExpansion(StructuralTypePriorityExpansionStrategy.java:69)
at org.semanticweb.owl.explanation.impl.blackbox.BlackBoxExplanationGenerator2.doExpansion(BlackBoxExplanationGenerator2.java:262)
at org.semanticweb.owl.explanation.impl.blackbox.BlackBoxExplanationGenerator2.computeExplanation(BlackBoxExplanationGenerator2.java:183)
at org.semanticweb.owl.explanation.impl.blackbox.BlackBoxExplanationGenerator2.generateExplanation(BlackBoxExplanationGenerator2.java:292)
at org.semanticweb.owl.explanation.impl.blackbox.hst.HittingSetTree.buildHittingSetTree(HittingSetTree.java:110)
at org.semanticweb.owl.explanation.impl.blackbox.BlackBoxExplanationGenerator2.getExplanations(BlackBoxExplanationGenerator2.java:118)
at org.semanticweb.owl.explanation.impl.blackbox.BlackBoxExplanationGenerator2.getExplanations(BlackBoxExplanationGenerator2.java:94)
at org.semanticweb.owl.explanation.impl.laconic.LaconicExplanationGenerator.computePreciseJustsOptimised(LaconicExplanationGenerator.java:173)
at org.semanticweb.owl.explanation.impl.laconic.LaconicExplanationGenerator.getExplanations(LaconicExplanationGenerator.java:386)
at msc.Explainer.explain(Explainer.java:46)
at msc.Explainer.lambda$2(Explainer.java:132)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1384)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:270)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at msc.Explainer.main(Explainer.java:132)
I have taken the ExplanationGenerationFactory function from this answer on getting explanations: Explanations in Consistent OWL Ontologies, as without it I couldn't get explanations at all.
This function tries to retrieve the topic of the GitHub repository name using the GitHub API: https://api.github.com/repos/flutter/flutter/topics
public List<String> getTopics(SearchRepository searchRepository){
GitHubRequest request = new GitHubRequest();
List<String> topic_list = new ArrayList<>();
try {
String url = searchRepository.getUrl().split("//")[1].split("github.com")[1];
request.setUri("/repos"+ url + "/topics");
String result = new BufferedReader(new InputStreamReader(gitHubClient.getStream(request)))
.lines().collect(Collectors.joining("\n"));
JSONObject jsonObject = new JSONObject(result);
topic_list = Arrays.stream(jsonObject.get("names").toString().replace("[", "").replace("]", "").split(",")).collect(Collectors.toList());
} catch (IOException e) {
e.printStackTrace();
}
return topic_list;
}
The url returned before string to list conversion is :https://github.com/repouser/reponame
SearchRepository is the v2 model class of Repository from the package:
SearchRepositroy
As per the earlier suggestions from this wonderful community answers (though the question is now edited, it remains yet relevant) I created the mock test to test the above function as below:
#Test
public void getTopicsTest() throws IOException{
SearchRepository mocksearchRepository = mock(SearchRepository.class);
GitHubClient mockClient = mock(GitHubClient.class);
GitHubRequest mockRequest = mock(GitHubRequest.class);
when(mocksearchRepository.getUrl()).thenReturn("https://github.com/mockuser/mockrepo");
when(mocksearchRepository.getName()).thenReturn("mockrepo");
when(mocksearchRepository.getOwner()).thenReturn("mockuser");
//when(mockRequest.setUri((String) any())).thenReturn(mockRequest.setUri("/repo/mockuser/mockrepo/topics"));
//The format of the return form is: https://github.com/CyC2018/CS-Notes
when(mockClient.getStream(any())).thenReturn(topicInputStream());
//SearchRepository querySearch = new SearchRepository("mockuser","mockrepo");
List<String> topics = githubServiceMock.getTopics(mocksearchRepository);
System.out.println(topics);
}
private InputStream topicInputStream() {
String mockTopics = "{" +
"topic1\": [" +
"topic2\"," +
"topic3\"," +
"skia" +
"]" +
"}";
InputStream stream = new ByteArrayInputStream(mockTopics.getBytes(StandardCharsets.UTF_8));
System.out.println(stream);
return stream;
}
However, I get the 404 internal server error Exception due to the request.setUri(Uri(String)) in the function. Please suggest where I am going wrong.
Test services.GithubServiceTest.getTopicsTest started
java.io.ByteArrayInputStream#6ed99482
org.eclipse.egit.github.core.client.RequestException: Not Found (404)
| => rat org.eclipse.egit.github.core.client.GitHubClient.createException(GitHubClient.java:552)
at org.eclipse.egit.github.core.client.GitHubClient.getResponseStream(GitHubClient.java:701)
at org.eclipse.egit.github.core.client.GitHubClient.getStream(GitHubClient.java:667)
at services.GithubService.getTopics(GithubService.java:231)
at services.GithubServiceTest.getTopicsTest(GithubServiceTest.java:222)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at com.novocode.junit.JUnitRunner$1.execute(JUnitRunner.java:132)
at sbt.ForkMain$Run.lambda$runTest$1(ForkMain.java:413)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
[]
[info] Test services.GithubServiceTest.getIssueWordLevelStatisticsTest started
[info] Test services.GithubServiceTest.getRepositoriesByTopicTest started
[info] Test services.GithubServiceTest.getUserDetailsTest started
[info] Test services.GithubServiceTest.getRepositoryDetailsTest started
[info] Test run finished: 0 failed, 0 ignored, 5 total, 1.122s
[error] Failed: Total 10, Failed 1, Errors 0, Passed 9
[error] Failed tests:
[error] controllers.GithubControllerTest
[error] (Test / test) sbt.TestsFailedException: Tests unsuccessful
You can mock repositoryService and gitHubClient to test various scenarios.
You can provide a package-level setter for these fields. It is a great idea to annotate it with Guava VisibleForTesting annotation.
Then you need to set mocks before the actual test on the instance.
Pseudocode for mocking
// First, we mock repository so we can return it from service
Repository repositoryMock = mock(Repository.class);
when(repository.getUrl()).thenReturn("https://...."); // You can return a URL or String, according to the mocked method's return type
// Then, we mock RepositoryService as well
RepositoryService repositoryServiceMock = mock(RepositoryService.class);
when(repositoryServiceMock.getRepository(anyString(), anyString()).thenReturn(repositoryMock);
// We mock gitHubService similarly
...
// After setting mock on the instance, we call the method and see if the results are expected
List<String> topics = getTopics("...", "...");
assertEquals(topics, ...);
// You can also assert interaction related things
verify(repositoryService).getRepository("a", "b"); // This is OK only if the service is called with "a" and "b" arguments
First, you need to inject the mock object (repositoryService,gitHubClient) to your function.
If you use spring/spring boot, you can consider to use #Mock and #MockBean annotation.
to mock the necessary bean.
The below code to create mock object manually.
RepositoryService fakeRs = Mockito.mock(RepositoryService.class);
GitHubClient fakeGHC = Mockito.mock(GitHubClient.class);
You also can use setter method to set mock object.
setRepositoryService(fakeRs);
setGitHubClient(fakeGHC);
The other way is using reflection utility to set private object.
ReflectionTestUtils.setField(yourService, "repositoryService", fakeRs);
ReflectionTestUtils.setField(yourService, "gitHubClient", fakeGHC);
After finish ingesting the mock object, you can write an test with expected behavior/data from mock object.
#Test
public void testGetTopics(){
// init mock object code in case setter/getter/reflection utils
Repository expectedRepository = createExampleRepository();
Mockito.when(repositoryService.getRepository(Mockito.anyString(),Mockito.anyString())
.thenReturn(expectedRepository);
// continue to fake gitHubClient with your expected data/ exceptions...
//call your method
List<?> data = yourService.getTopic("user","data");
Assertions.assertTrue(data!=null);
// you can write few assertion base on your fake datas
}
PS: Don't copy/paste the code, you will get compile errors. I am not using editor tool.
I am trying to get used to python+java interaction and so I wrote a little python-script that I wanted to execute that script from my Spring Boot Application. That script is located in the (relative from the .java-file) path /scripts_py/getStockPrice.py that contains the getStockPrice-method (see code below). So I integrated jython and tried to execute the following CronJob:
#Component
public class CronService {
private PythonScriptSingleton pss = PythonScriptSingleton.getInstance();
private final Logger logger = LoggerFactory.getLogger(CronService.class);
//call every 5 sec
#Scheduled(fixedRate = 5000)
public void initStockPriceAPICall() {
this.getStockPrice("NFLX");
}
public void getStockPrice(String ticker) {
String result = (String) (Object) this.pss.getFunc_getPriceForTicker().__call__(new PyString(ticker));
try {
logger.info("Price is " + result);
} catch (NullPointerException e) {
logger.info("Catched NPE");
}
}
}
The PythongScriptSingleton (the idea was, that I probably need to execute that script a lot of times - so I tried to go for a singleton instance of this class that holds the script so I do not need to recompile it every time:
public class PythonScriptSingleton {
private static PythonScriptSingleton ps;
public static PythonScriptSingleton getInstance() {
if (ps == null) {
ps = new PythonScriptSingleton();
ps.initScript();
}
return ps;
}
private PyObject func_getPriceForTicker;
private PythonScriptSingleton() {
}
private void initScript() {
PythonInterpreter interpreter = new PythonInterpreter();
String fileUrlPath = "/scripts_py";
String scriptName = "getStockPrice.py";
interpreter.exec("import sys\n" + "import os \n" + "sys.path.append('" + fileUrlPath + "')\n" + "from "
+ scriptName + " import * \n");
String funcName = "getStockPrice";
PyObject someFunc = interpreter.get(funcName);
this.func_getPriceForTicker = someFunc;
interpreter.close();
}
public PyObject getFunc_getPriceForTicker() {
return func_getPriceForTicker;
}
}
The Python Script:
from yahoo_fin import stock_info as si
def getStockPrice(ticker):
price = si.get_live_price(ticker)
return price
I am using the embedded tomcat with Spring Boot (executable JAR-File) and jython-standalone 2.7.2:
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.2</version>
</dependency>
The error i keep running into says, that the script is not defined - I tried defining it with and without the file ending (.py), both did not change anything:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [de.fr.stockticker.pythoninteraction.CronService]: Constructor threw exception; nested exception is Traceback (most recent call last):
File "<string>", line 4, in <module>
ImportError: No module named getStockPrice
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:217) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1312) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
... 81 common frames omitted
Caused by: org.python.core.PyException: ImportError: No module named getStockPrice
at org.python.core.Py.ImportError(Py.java:329) ~[jython-standalone-2.7.2.jar:2.7.2]
at org.python.core.imp.import_first(imp.java:1230) ~[jython-standalone-2.7.2.jar:2.7.2]
at org.python.core.imp.import_module_level(imp.java:1361) ~[jython-standalone-2.7.2.jar:2.7.2]
at org.python.core.imp.importName(imp.java:1528) ~[jython-standalone-2.7.2.jar:2.7.2]
at org.python.core.ImportFunction.__call__(__builtin__.java:1285) ~[jython-standalone-2.7.2.jar:2.7.2]
at org.python.core.PyObject.__call__(PyObject.java:433) ~[jython-standalone-2.7.2.jar:2.7.2]
at org.python.core.__builtin__.__import__(__builtin__.java:1232) ~[jython-standalone-2.7.2.jar:2.7.2]
at org.python.core.imp.importAll(imp.java:1647) ~[jython-standalone-2.7.2.jar:2.7.2]
at org.python.pycode._pyx0.f$0(<string>:4) ~[na:na]
at org.python.pycode._pyx0.call_function(<string>) ~[na:na]
at org.python.core.PyTableCode.call(PyTableCode.java:173) ~[jython-standalone-2.7.2.jar:2.7.2]
at org.python.core.PyCode.call(PyCode.java:18) ~[jython-standalone-2.7.2.jar:2.7.2]
at org.python.core.Py.runCode(Py.java:1687) ~[jython-standalone-2.7.2.jar:2.7.2]
at org.python.core.Py.exec(Py.java:1731) ~[jython-standalone-2.7.2.jar:2.7.2]
at org.python.util.PythonInterpreter.exec(PythonInterpreter.java:268) ~[jython-standalone-2.7.2.jar:2.7.2]
at de.fr.stockticker.pythoninteraction.PythonScriptSingleton.initScript(PythonScriptSingleton.java:28) ~[classes/:na]
at de.fr.stockticker.pythoninteraction.PythonScriptSingleton.getInstance(PythonScriptSingleton.java:13) ~[classes/:na]
at de.fr.stockticker.pythoninteraction.CronService.<init>(CronService.java:12) ~[classes/:na]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_251]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_251]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_251]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_251]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:204) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
... 83 common frames omitted
I was able to run your program partially using Jython - I couldn't get the stock process from yahoo which is internally depends on numpy and looks like Jython doesn't support numpy as it being cpython library.
private void initScript() {
PythonInterpreter interpreter = new PythonInterpreter();
String fileUrlPath = "/users/sagar/demo/src/main/resources/python";
interpreter.exec("import sys");
interpreter.exec("sys.path.append('" + fileUrlPath + "')");
interpreter.exec("from getStockPrice import *"); this.func_getPriceForTicker =
interpreter.get("getStockPrice", PyFunction.class);
interpreter.close();
}
You will be able to get past your error but you will see error
Missing required dependencies ['numpy']
So I tried using another java python library jep and made changes as follow
#SpringBootApplication
#EnableScheduling
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
private final Logger logger = LoggerFactory.getLogger(DemoApplication.class);
//call every 5 sec
#Scheduled(fixedRate = 5000)
public void initStockPriceAPICall() throws JepException {
this.getStockPrice("NFLX");
}
private void getStockPrice(String ticker) throws JepException {
try (Interpreter interp = new SharedInterpreter()) {
String fileUrlPath = "/users/sagar/demo/src/main/resources/python";
interp.exec("import sys");
interp.exec("sys.path.append('" + fileUrlPath + "')");
interp.exec("from getStockPrice import *");
interp.set("ticker", ticker);
interp.exec("price = getStockPrice(ticker)");
Object result = interp.getValue("price");
logger.info("Price is " + result);
}
}
}
pom.xml
<dependency>
<groupId>black.ninia</groupId>
<artifactId>jep</artifactId>
<version>3.9.0</version>
</dependency>
Make sure to install jep module - it has native library
pip install jeb
Add java library path to load native library
-Djava.library.path=/usr/local/lib/python2.7/site-packages/jep
Reference - https://github.com/ninia/jep/wiki/Getting-Started
I am using ASM 5.0.3 with Websphere 8.5.x and IDM JDK 1.7 to profiling method execution time using org.objectweb.asm.commons.AdviceAdapter
Oracle JDBC driver ojdbc7.jar is used for creating JDBC. My Application is working fine without adding -javaagent arguments.
When bytecode is modified (via -javaagent), Websphere starts fine but when accessing application it throws java.lang.NoClassDefFoundError: oracle/security/pki/OraclePKIProvider .
I found a link which explains about the issue in detail & shows NoClassDefFoundError happens for certain JVM/driver version combinations
https://plumbr.eu/blog/java/troubleshooting-verifiers-the-rabbit-hole-goes-deep
An exception occurred while invoking method setDataSourceProperties on com.ibm.ws.rsadapter.spi.WSManagedConnectionFactoryImpl used by resource jdbc/appDatasource : java.lang.NoClassDefFoundError: oracle/security/pki/OraclePKIProvider
at oracle.jdbc.pool.OracleDataSource.<clinit>(OracleDataSource.java:103)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:383)
at com.ibm.ws.rsadapter.DSConfigHelper.createDataSource(DSConfigHelper.java:747)
at com.ibm.ws.rsadapter.spi.WSRdbDataSource.createNewDataSource(WSRdbDataSource.java:3029)
at com.ibm.ws.rsadapter.spi.WSRdbDataSource.<init>(WSRdbDataSource.java:1358)
at com.ibm.ws.rsadapter.spi.WSManagedConnectionFactoryImpl.setDataSourceProperties(WSManagedConnectionFactoryImpl.java:2653)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
......
Suggested solution from the link is
Make sure that if the label visit was originally followed by a frame visit, we would insert our instructions after the frame visit, not between the frame and the label.
Can some one explain "How to achieve this using ASM bytecode?"
Update1 - Attached AdviceAdapter Code
package com.abc.agent.adapter;
import com.abc.jm.TMConstants;
import com.abc.jm.TMLog;
import com.abc.org.objectweb.asm.Label;
import com.abc.org.objectweb.asm.MethodVisitor;
import com.abc.org.objectweb.asm.Opcodes;
import com.abc.org.objectweb.asm.Type;
import com.abc.org.objectweb.asm.commons.AdviceAdapter;
public class DriverMethodAdviceAdapter extends AdviceAdapter {
private String methodName;
private String className;
private String description;
private boolean isConnectMethod;
private static final String INTERFACE_DRIVER_CONNECT_METHOD_DESC = "(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;";
private int okFlag = newLocal(Type.BOOLEAN_TYPE);
Label startFinally = new Label();
public DriverMethodAdviceAdapter(int access , MethodVisitor mv , String methodName, String description, String className, int classFileVersion){
super(Opcodes.ASM5, mv, access, methodName, description);
this.className = className;
this.methodName = methodName;
this.description = description;
this.isConnectMethod = false;
if(methodName.equals("connect") && description.equals(INTERFACE_DRIVER_CONNECT_METHOD_DESC)){
isConnectMethod = true;
}
}
public void visitCode() {
super.visitCode();
mv.visitLabel(startFinally);
}
protected void onMethodEnter(){
if(isConnectMethod){
mv.visitInsn(Opcodes.ICONST_0);
mv.visitVarInsn(ISTORE, okFlag);
mv.visitLdcInsn(className);
mv.visitLdcInsn(methodName);
mv.visitLdcInsn(description);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/abc/agent/trace/Tracer", "jdbcConnectionMethodBegin", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", false);
mv.visitVarInsn(ISTORE, okFlag);
}
}
protected void onMethodExit(int opcode){
if(opcode!=ATHROW) {
onFinally(opcode);
}
}
public void visitMaxs(int maxStack, int maxLocals){
Label endFinally = new Label();
mv.visitTryCatchBlock(startFinally, endFinally, endFinally, null);
mv.visitLabel(endFinally);
onFinally(ATHROW);
mv.visitInsn(ATHROW);
mv.visitMaxs(maxStack+4, maxLocals);
}
private void onFinally(int opcode){
if(isConnectMethod){
mv.visitInsn(Opcodes.DUP); // This is return object
mv.visitLdcInsn(className);
mv.visitLdcInsn(methodName);
mv.visitLdcInsn(description);
mv.visitVarInsn(ILOAD, okFlag);
mv.visitLdcInsn(opcode);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/abc/agent/trace/Tracer", "jdbcConnectionMethodEnd", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZI)V", false);
}
}
}
I am using the flags ClassWriter.COMPUTE_FRAMES for ClassWriter and ClassReader.EXPAND_FRAMES | ClassReader.SKIP_FRAMES for ClasseReader.accept().
I wanted to create a simple template wizard for NetBeans that would take an existing Java class from current user project and create a new Java class from it. To do so, I need to access field and annotation data from the selected class (Java file).
Now, I used the org.netbeans.api.java.source.ui.TypeElementFinder for finding and selecting the wanted class, but as a result I get an ElementHandle and I don't know what to do with it. How do I get class info from this?
I managed to get a TypeMirror (com.sun.tools.javac.code.Type$ClassType) using this code snippet:
Project project = ...; // from Templates.getProject(WizardDescriptor);
ClasspathInfo ci = ClasspathInfoFactory.infoFor(project, true, true, true);
final ElementHandle<TypeElement> element = TypeElementFinder.find(ci);
FileObject fo = SourceUtils.getFile(element, ci);
JavaSource.forFileObject(fo).runUserActionTask(new Task<CompilationController>() {
#Override
public void run(CompilationController p) throws Exception {
p.toPhase(JavaSource.Phase.RESOLVED);
TypeElement typeElement = element.resolve(p);
TypeMirror typeMirror = typeElement.asType();
}
}, true);
But what to do form here? Am I going about this the wrong way altogether?
EDIT:
In, response to francesco foresti's post:
I tried loads of different Reflection/Classloader approaches. I got to a point where a org.netbeans.api.java.classpath.ClassPath instance was created and would contain the wanted Class file, but when I tried loading the said class with a Classloader created from that ClassPath, I would get a ClassNotFoundException. Here's my code:
Project project = ...; // from Templates.getProject(WizardDescriptor);
ClasspathInfo ci = ClasspathInfoFactory.infoFor(project, true, true, true);
final ElementHandle<TypeElement> element = TypeElementFinder.find(ci);
FileObject fo = SourceUtils.getFile(element, ci);
ClassPath cp = ci.getClassPath(ClasspathInfo.PathKind.SOURCE);
System.out.println("NAME: " + element.getQualifiedName());
System.out.println("CONTAINS: " + cp.contains(fo));
try {
Class clazz = Class.forName(element.getQualifiedName(), true, cp.getClassLoader(true));
System.out.println(clazz.getName());
} catch (ClassNotFoundException ex) {
Exceptions.printStackTrace(ex);
}
This yields:
NAME: hr.test.Test
CONTAINS: true
SEVERE [org.openide.util.Exceptions]
java.lang.ClassNotFoundException: hr.test.Test
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at org.openide.execution.NbClassLoader.findClass(NbClassLoader.java:210)
at org.netbeans.api.java.classpath.ClassLoaderSupport.findClass(ClassLoaderSupport.java:113)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:344)
why don't you use plain old reflection? E.g.
Class<?> theClazz = Class.forName("com.example.myClass");
Annotation[] annotations = theClazz.getAnnotations();
Field[] fields = theClazz.getFields();
Method[] methods = theClazz.getMethods();
// from here on, you write a file that happens to be in the classpath,
// and whose extension is '.java'