Based on the WordCount Example, I am trying to read my own json data (instead of the shakespear txts).
I am running the pipeline with:
mvn compile exec:java -Dexec.mainClass=myPkg.myClass -Dexec.args=" \
--project=myProj \
--stagingLocation=gs://myBkt/stage \
--runner=BlockingDataflowPipelineRunner \
--output=gs://myBkt/output/out \
--defaultWorkerLogLevel=DEBUG"
the output from the console is as follows:
<date> com.google.cloud.dataflow.sdk.runners.DataflowPipelineRunner fromOptions
INFO: PipelineOptions.filesToStage was not specified. Defaulting to files from the classpath: will stage 68 files. Enable logging at DEBUG level to see which files will be staged.
<date> myPkg$GroupPublished apply
<date> myPkg$GroupPublished apply
INFO: GroupPublished/JsonToDatePosPlatKeyFn.out [PCollection]
<date> myPkg main
main
static void main(String[] args) {
...
Pipeline p = Pipeline.create(options);
p.apply(TextIO.Read.named("ReadJson").from(options.getInputFile()))
.apply(new GroupPublished())
.apply(ParDo.of(new FormatAsStringFn()))
.apply(TextIO.Write.named("WriteCounts").to(options.getOutput()));
}
GroupPublished transformation
static class GroupPublished extends PTransform<PCollection<String>,
PCollection<KV<DatePosPlatKey, Long>>> {
#Override
public PCollection<KV<DatePosPlatKey, Long>> apply(PCollection<String> lines) {
PCollection<DatePosPlatKey> keyList
= lines.apply(ParDo.of(new JsonToDatePosPlatKeyFn()));
PCollection<KV<DatePosPlatKey, Long>> keysCounted =
keyList.apply(Count.<DatePosPlatKey>perElement());
return keysCounted;
}
}
json row processing
static class JsonToDatePosPlatKeyFn extends DoFn<String, DatePosPlatKey>{
#Override
public void processElement(ProcessContext c) throws Exception {
JsonNode root = mapper.readTree(c.element());
for (JsonNode jsonFact : root) {
DatePosPlatKey key = new DatePosPlatKey(...construct...);
...manipulate...
c.output(key);
}
}
}
data class
#DefaultCoder(AvroCoder.class)
public static class DatePosPlatKey { ... }
stuff I've checked so far:
adding defaultWorkerLogLevel doesn't seem to make any difference to the console output
renaming the json file throws an error, so I know its been seen by TextIO
the json files have data in the format: {...}\n{...}\n...
no logging or dataflow job appears in the google cloud console
how can I better debug a complete lack of data?
can you see what I've done wrong?
Upon offline discussion it turned out the code was missing a call to p.run(), so the pipeline was only constructed but not executed.
Related
I am learning apache camel, I have created one spring boot project in which i want to validate the message body with json schema. In my project, I have create route in which i am fetching file from the location in my computer and then passing it to next endpoint where i have applied json validator component and then passed to seda endpoint where i consumed the output.
The code is as follow :
#SpringBootApplication
public class ExampleCamelDemoApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(ExampleCamelDemoApplication.class, args);
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder() {
public void configure() throws Exception {
//
from("file:C:\\sourceFolder?fileName=test.json&noop=true").convertBodyTo(String.class).to("json-validator:classpath:myschema.json")
.to("seda:end");
}
});
context.start();
ConsumerTemplate ct = context.createConsumerTemplate();
System.out.println(ct.receiveBody("seda:end"));
Thread.sleep(10000);
context.stop();
}
}
the test.json file content is :
{
"id" :1
}
and myschema.json file content is :
{
"id" :1
}
I placed the myschema.json file in src/main/resources folder
I am getting error :
Message History (complete message history is disabled)
RouteId ProcessorId Processor Elapsed (ms)
[route1 ] [route1 ] [from[file://C:%5CsourceFolder?fileName=test.json&noop=true] ] [ 2]
...
[route1 ] [to1 ] [json-validator:classpath:myschema.json ] [ 0]
Stacktrace
java.lang.NullPointerException: null
at com.networknt.schema.JsonSchema.combineCurrentUriWithIds(JsonSchema.java:87) ~[json-schema-validator-1.0.29.jar:na]
at com.networknt.schema.JsonSchema.(JsonSchema.java:75) ~[json-schema-validator-1.0.29.jar:na]
at com.networknt.schema.JsonSchema.(JsonSchema.java:62) ~[json-schema-validator-1.0.29.jar:na]
at com.networknt.schema.JsonSchema.(JsonSchema.java:57) ~[json-schema-validator-1.0.29.jar:na]
at com.networknt.schema.JsonSchemaFactory.newJsonSchema(JsonSchemaFactory.java:253) ~[json-schema-validator-1.0.29.jar:na]
Either this is a copy/paste mistake or your schema file is not a JSON schema, but the same as your json data.
Take a look at the Camel docs for an example of a JSON schema file that can be used with the validator.
I have a Spring Batch Task running on our cloud platform that will launch with the provided command line parameters, and then skip over the execution of the first Step with the following error:
[OUT] The job execution id 992 was run within the task execution 1325
[OUT] Step already complete or not restartable, so no action to execute:
StepExecution: id=1071, version=3, name=OFileStep, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0,
writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
I have investigated the metadata tables in the MySQL instance that Spring Batch uses to find that the JOB_INSTANCE_ID is the same between multiple executions, when it should increment by 1 each time.
The #Bean that I have defined for the Job Configuration is:
#Bean
public Job job() {
return jobBuilderFactory.get(OTaskConstants.JOB_NAME)
.listener(listener())
.incrementer(new RunIdIncrementer())
.start(dataTransferTaskStep())
.next(controlMTaskStep())
.build();
}
Is anyone aware of what could be causing this behavior?
Below line clearly says it all.
Step already complete or not restartable, so no action to execute:
Meaning the step/job already complete and can not be restarted. This is the behavior of Spring Batch. In order to by pass this we need to pass an unique argument.
In your case i see you already have RunIdIncrementer. Now question is why it is not working.
Can you see BATCH_JOB_PARMS table to see what arguments are getting passed to the job? May be you are missing something.
You can also use SimpleIncrementor. See below code for explanation.
https://docs.spring.io/spring-batch/docs/current/reference/html/index-single.html#JobParametersIncrementer
Remove #Bean annotation on Job.
It causes the Job to be launched with no parameters every time you launch/start application as spring tries to load the bean and which in-turn launches the batch job.
Remove the annotation and use spring scheduler to schedule the jobs.
I had the same issue. Below code helped me resolve it. By adding params in job launcher a new job_instance_id is created for every run.
#SpringBootApplication
public class App implements CommandLineRunner {
#Autowired
JobLauncher jobLauncher;
#Autowired
Job job;
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
#Override
public void run(String... args) throws Exception {
JobParameters params = new JobParametersBuilder()
.addString("JobID", String.valueOf(System.currentTimeMillis()))
.toJobParameters();
jobLauncher.run(job, params);
}
}
Solution
Refer error message above “If you want to run this job again, change the parameters.” The formula is JobInstance = JobParameters + Job. If you do not have any parameters for JobParameters, just pass a current time as parameter to create a new JobInstance. For example,
CustomJobLauncher.java
//...
#Component
public class CustomJobLauncher {
#Autowired
JobLauncher jobLauncher;
#Autowired
Job job;
public void run() {
try {
JobParameters jobParameters =
new JobParametersBuilder()
.addLong("time",System.currentTimeMillis()).toJobParameters();
JobExecution execution = jobLauncher.run(job, jobParameters);
System.out.println("Exit Status : " + execution.getStatus());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Source : https://mkyong.com/spring-batch/spring-batch-a-job-instance-already-exists-and-is-complete-for-parameters/
In a command line Java application you can get arguments through the args parameter:
public static void main(String[] args) {
How can I do something similar in Ceylon? I tried copying the Java style:
shared void run(String[] args) {
but got an error since that is not allowed:
ceylon run: Cannot run toplevel method 'test.project.run':
it should have no parameters or they should all have default values.
I've been reading the ceylon-lang.org tour but I haven't found the answer.
Use the top-level process object in the language module.
String[] arguments = process.arguments;
String? argument = process.namedArgumentValue("name");
if (process.namedArgumentPresent("name")) {
// ...
}
To tell you first, i have tried and tried it again and now i need some help
Heres my code
package staticPkg;
public class Static {
public static final String staticMethod() {
System.out.println("Static method called");
return "Static called";
}
}
package staticPkg;
public class TargetClass {
Static staticClass;
public String callHere() {
return Static.staticMethod();
}
}
package staticPkg;
import org.easymock.EasyMock;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.testng.IObjectFactory;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;
#PrepareForTest({Static.class})
public class TestClass {
Static staticClass = null;
#ObjectFactory
public IObjectFactory getObjectFactory() {
System.out.println("got object factory");
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
#BeforeMethod
public void setup() {
System.out.println("print me");
PowerMock.mockStatic(Static.class);
staticClass = PowerMock.createMock(Static.class);
}
#Test
public void testMe() {
EasyMock.expect(Static.staticMethod()).andReturn("Mock called").anyTimes();
PowerMock.replay(Static.class,staticClass);
TargetClass tc = new TargetClass();
String output = tc.callHere();
PowerMock.verify(Static.class,staticClass);
System.out.println(output);
}
}
And heres the log
[Parser] Running:
C:\MockWorkspace\Mock\temp-testng-customsuite.xml
got object factory
print me
Static method called
FAILED: testMe
java.lang.IllegalStateException: no last call on a mock available
at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:521)
at org.easymock.EasyMock.expect(EasyMock.java:499)
at staticPkg.TestClass.testMe(TestClass.java:46)
... Removed 22 stack frames
===============================================
staticPkg.TestClass
Tests run: 1, Failures: 1, Skips: 0
===============================================
===============================================
Mock
Total tests run: 1, Failures: 1, Skips: 0
===============================================
Help please, i have tried a variety of solutions, can't get it done.
Please can anyone try this code and correct it for success?
I get error in EasyMock.expect ...............
Got a work around at http://blogs.bytecode.com.au/glen/2006/10/12/doing-bytecode-kungfu-with-javassist.html
And it works
But wait..........I am stuck again
My testcase works fine when runs alone, but when run with Ant, it gives problem. Might be other test cases of different files are interfering.
I got the same error, when my individual test case was using #PrepareTest & easymock/powermock
[testng] ====================STATIC CALLED===========================
[testng] javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClass
Loader): attempted duplicate class definition for name: "com/symantec/mobius/aggregator/submission/SubmissionFactory"
[testng] at javassist.ClassPool.toClass(ClassPool.java:1085)
[testng] at javassist.ClassPool.toClass(ClassPool.java:1028)
[testng] at javassist.ClassPool.toClass(ClassPool.java:986)
[testng] at javassist.CtClass.toClass(CtClass.java:1110)
Try extending from PowerMockTestCase. The TestNG support will also be updated in next version of PowerMock (1.4.9).
I faced this same issue, and struggled a lot. Finally, found the following solution:
Another alternative is to set the object-factory to org.powermock.modules.testng.PowerMockObjectFactory in the TestNG suite.xml. Here is a sample suite file:
<suite name="dgf" verbose="10" object-factory="org.powermock.modules.testng.PowerMockObjectFactory">
<test name="dgf">
<classes>
<class name="com.example.ClientTest"/>
</classes>
</test>
</suite>
Of course, you can also extend your test case from PowerMockTestCase as told by Johan.
Mock all the static methods in static class before proceeding to mock the static method. Try with this:
#Test
public void testMe() {
PowerMock.mockStatic(Static.class);
EasyMock.expect(Static.staticMethod()).andReturn("Mock called").anyTimes();
PowerMock.replay(Static.class,staticClass);
TargetClass tc = new TargetClass();
String output = tc.callHere();
PowerMock.verify(Static.class,staticClass);
System.out.println(output);
}
All,
I am currently using JUnit 4 for writing test cases. I am fairly new to JUnit and finding it difficult to test my main class which takes arguments. I have specified the arguments to my JUnit test class by:
1 > Right click JUnit test class
2 > Goto Run As -> Run Configurations
3 > Select the Arguments tab and specify a value (I have entered an invalid argument i.e. the main class expects the command line argument to be converted to an int and I am passing a String value that cannot be converted to int)
However, the main class that I am testing, if the command line argument cannot be converted to a int, than I throw IllegalArgumentException. However, the JUnit does not show the testMain() method as Error or Failure. I don't think my setup is right for the JUnit class. Can anyone please guide me where I am going wrong
To test your class main method simply write something like:
#Test(expected = IllegalArgumentException.class)
public void testMainWithBadCommandLine()
{
YourClass.main(new String[] { "NaN" });
}
Change the main() method to something like this:
public static void main(String[] args)
{
MyClass myclass = new MyClass(args);
myclass.go();
}
Move the code that was in main() to the new method go(). Now, your test method can do this:
public void myClassTest()
{
String[] args = new String[]{"one", "two"}; //for example
MyClass classUnderTest = new MyClass(testArgs);
classUnderTest.go();
}
Firstly the arguments should be in the program arguments section. Normally the launching point of the application that's the main method doesn't need to be tested if you design the app to be testable.
Refactor the class
public static class ArgumentValidator
{
public static boolean nullOrEmpty(String [] args)
{
if(args == null || args.length == 0)
{
throw new IllegalArgumentException(msg);
}
//other methods like numeric validations
}
}
You can now easily test the nullOrEmpty method using junit like
#Test(expected = IllegalArgumentException.class)
public void testBadArgs()
{
ArgumentValidator.nullOrEmpty(null);
}
I think this is a better approach