Upgrading from BIRT 2.5.2 to 3.7.1 - war

We previously used the code below to set up BIRT Engine to use within our servlet, the migration guide says you just need to add the BIRT jars to the classpath, the BIRT jars were added to WEB-INF\lib.
When we run the app now, IReportEngineFactory returns null. Any help is appreciated.
public static synchronized IReportEngine getBirtEngine(ServletContext sc) throws Exception {
EngineConfig config = new EngineConfig();
config.setBIRTHome("");
config.setLogConfig("C:/Temp", Level.FINEST);
config.setLogFile("birtLog.log");
realPath = sc.getRealPath("/reports");
log.info("Server Info: " + sc.getServerInfo());
log.info(" Servlet Context Name: " + sc.getServletContextName());
log.info("Real Path: " + realPath);
log.info("#####Creating new Birt Engine#####");
//log.info("Birt Home is: " + config.getBIRTHome());
IPlatformContext context = new PlatformServletContext(sc);
config.setPlatformContext(context);
try {
Platform.startup(config);
//log.info("Birt Home is: " + config.getPlatformContext().toString());
IReportEngineFactory factory = (IReportEngineFactory) Platform.createFactoryObject
(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
birtEngine = factory.createReportEngine(config);
}
catch (Exception e ) {
throw e;
}
return birtEngine;
}

Adding the following line solved the problem in my custom BirtEngine.java configuration:
IPlatformContext context = new PlatformServletContext(sc);
config.getAppContext().put(EngineConstants.WEBAPP_CLASSPATH_KEY, "");

On many posts in the net I read you must not set BIRT home and platform context anymore. So your code should become something like this:
public static synchronized IReportEngine getBirtEngine() throws Exception {
EngineConfig config = new EngineConfig();
config.setLogConfig("C:/Temp", Level.FINEST);
config.setLogFile("birtLog.log");
try {
Platform.startup(config);
IReportEngineFactory factory = (IReportEngineFactory) Platform.createFactoryObject
(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
birtEngine = factory.createReportEngine(config);
}
catch (Exception e ) {
throw e;
}
return birtEngine;
}

Related

How to avoid extent report to not to overwrite the html file name

I am using extent reports in appium with testng and its working fine for me.whenver my tests run is completed then extent report generates html file in my project folder and that is what expected.
Issue is that when I again run my tests then extent report generate new html report file by overwrting the name of previously created html file.
I want extent report to generate html file with unique names or name with date in in, each time when I run my tests
You can create your file name to be the current timestamp. This way, it will be easy to have a unique name for your report file -
String timeStamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date());
extent = new ExtentReports (userDir +"\\test-output\\" + timeStamp + ".html", true);
You can do it by setting unique name:
String reportFile = resultDirectory + fileName + ".html";
than method for saving report to certain folder:
public void saveReportFolder() throws IOException {
File srcDir = new
File(System.getProperty("user.home")+"/Automation/target");
File destDir = new File(System.getProperty("user.home") + "/reports/"+ System.getProperty("user.name")+"/"+dateTimeGenerator());
FileUtils.copyDirectory(srcDir, destDir);
}
...and utility for setting dateTime:
public static String dateTimeGenerate(){
Format formatter = new SimpleDateFormat("YYYYMMdd_HHmmssSSS");
Date date = new Date(System.currentTimeMillis());
return formatter.format(date);
}
Or simply use klov reports start server and have everything in database (MongoDb), it is more elegant way to go.
Hope this helps,
I use:
private static String timestamp = new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime()).replaceAll(":", "-");
public static String reportFullPath = getReportsPath() + "\\AutomationReport_" + timestamp + ".html";
I have done it like this, simple and crisp.
String Outputfilename= ExecutionConfig.FileOutname;
System.err.close(); // written to remove JAVA 9 incompatibility.. continued below
System.setErr(System.out); // continue.. and remove the warnings
extent = new ExtentReports(System.getProperty("user.dir") + "/test-output/"+Outputfilename+".html", true);
So here ExecutionConfig.FileOutname is called from the class ExecutionConfig where i am reading the values from the config.properties file. and then here assigning it to the output-file.
Also it worked for me.
I also faced a similar issue. As in the real-world, we need old reports as well. Below is the solution in Java for Extent PDF report
I added an event listener method. Event used- TestRunStarted. We further need to register for this event too. The solution can be done for HTML report too.
public void setCustomReportName(TestRunStarted event)
{
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss");
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
String currenttimestamp =sdf.format(timestamp);
Properties prop=new Properties();
//extent.reporter.pdf.out is the name of property which tell the report path
prop.setProperty("extent.reporter.pdf.out", "test output/PdfReport/ExtentPdf_"+currenttimestamp+".pdf");
ExtentService e1 =new ExtentService();
//ExtentReportsLoader is the inner class of ExtentService and initPdf is its private method which takes the path for report
Class<?>[] a=e1.getClass().getDeclaredClasses();
Method met;
//Even there is exception test run wont fail and report will also be generated (ExtentPdf.pdf)
try {
met = a[0].getDeclaredMethod("initPdf", Properties.class);
met.setAccessible(true);
met.invoke(a[0], prop);
} catch (NoSuchMethodException e) {
System.out.println("There is no method with name initPdf");
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
System.out.println("Argument passed to method initPdf are not correct");
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}

toCompletableFuture() stucks for asynchronous cache

Hello there I am trying to force a promise to end to get the result from it but it just stucks on loading.
public class CacheController extends Controller {
private AsyncCacheApi cache;
public Result cache()
{
String test = "nice";
cache.set("item.key", test, 15);
Customer user = new Customer("Ana", 12);
CompletionStage<Done> result = cache.set(user.getName(), user);
block(result);
return ok("Cached");
}
public Result checkCache() throws Exception
{
Logger.info("start");
//CompletionStage<String> news = cache.get("item.key");
//news.thenRun(() -> System.out.println("works"));
CompletionStage<Customer> result = cache.get("Ana");
Logger.info("step 1");
Logger.info(cache.get("Ana").toString());
Logger.info("Step 2");
Customer c = block(result);
Logger.info("Step 3 " + c.getName());
//result.thenRun(() -> setUser(result)).thenRun(() -> Logger.info(user.getName() + " " + user.getAge()));
return ok("cancan");
}
private <T> T block(CompletionStage<T> stage) {
try {
return stage.toCompletableFuture().get();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
When trying to load the page it gets stuck after step2 at line 56: Customer c = block(result); by my guesses
Any ideas to fix it?
#Codrin
I had the same problem. But, see https://www.playframework.com/documentation/2.6.x/JavaCache#Setting-the-execution-context
By default, all Ehcache operations are blocking, and async implementations will block threads in the default execution context.
Maybe CompletableFuture.get() gets stuck because it is executed in the same thread with the caller.
Referring to the linked page, I added snippet below to my application.conf and it worked.
play.cache.dispatcher = "contexts.blockingCacheDispatcher"
contexts {
blockingCacheDispatcher {
fork-join-executor {
parallelism-factor = 3.0
}
}
}

Google Cloud Vision crashes without exception caught

I recently encountering an annoying bug that only happen in 1 out of our 3 environments (Amazon EC2 to be specific). When I send a request to the Cloud API to receive tags about the picture. The function crashes but I don't see any exception caught by the try catch. The function works fine until June 1st but I don't know why it doesn't anymore (other 2 environments work just fine).
Here are the code:
try {
GoogleCredentials cred = GoogleCredentials.fromStream(new FileInputStream(coreConfig.googleCreds()));
log.error("GoogleCredentials cred = GoogleCredentials.fromStream(new FileInputStream(coreConfig.googleCreds()));");
ImageAnnotatorSettings imageAnnotatorSettings = ImageAnnotatorSettings.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(cred))
.build();
ImageAnnotatorClient vision = ImageAnnotatorClient.create(imageAnnotatorSettings);
log.error("ImageAnnotatorClient vision = ImageAnnotatorClient.create(imageAnnotatorSettings);");
byte[] data = IOUtils.toByteArray(is);
ByteString bs = ByteString.copyFrom(data);
// Builds the image annotation request
List<AnnotateImageRequest> requests = new ArrayList<>();
log.error("ByteString bs = ByteString.copyFrom(data);");
Image img = Image.newBuilder().setContent(bs).build();
log.error(" Image img = Image.newBuilder().setContent(bs).build();");
Feature feat = Feature.newBuilder().setType(Type.LABEL_DETECTION).build();
log.error("Feature feat = Feature.newBuilder().setType(Type.LABEL_DETECTION).build();");
AnnotateImageRequest request = AnnotateImageRequest.newBuilder()
.addFeatures(feat)
.setImage(img)
.build();
requests.add(request);
log.error("requests.add(request);");
// Performs label detection on the image file
BatchAnnotateImagesResponse response = vision.batchAnnotateImages(requests);
log.error("BatchAnnotateImagesResponse response = vision.batchAnnotateImages(requests);");
List<AnnotateImageResponse> responses = response.getResponsesList();
log.error("List<AnnotateImageResponse> responses = response.getResponsesList();");
for (AnnotateImageResponse res : responses) {
if (res.hasError()) {
throw new ServiceException(ServiceStatus.BAD_REQUEST, res.getError().getMessage());
}
for (EntityAnnotation annotation : res.getLabelAnnotationsList()) {
tags.append("===" + annotation.getDescription().replaceAll("\\s+",""));
log.error("tags.append(\"===\" + annotation.getDescription().replaceAll(\"\\\\s+\",\"\"));");
}
}
return tags;
}catch(Exception e) {
e.printStackTrace();
log.error(e.getMessage());
return null;
// throw new ServiceException(ServiceStatus.BAD_REQUEST, e.getMessage());
}
Here are the details about it:
It seems like an old version of guava (in this case 17.0-jdk) caused this crash.
You still have to remove the old version not only from the pom.xml but also in the lib folder of the .war file.

How to perform Multiple write opeartion on a single file?

I have a website in asp.net 2.0 which write some thing on a file. But at the same time if another user hit that site it does not work till the first one operation on the file completed after that second one can do operation with the files.
How to handle such situation.
AppConfiguration appConfiguration = new AppConfiguration();
string LogFile =String.Empty;
string sLogFormat =string.Empty;
string sErrorTime =string.Empty;
StreamWriter sw=null;
public LogManager()
{
if(!File.Exists(AppConfiguration.LogFilePath))
{
Directory.CreateDirectory(AppConfiguration.LogFilePath);
}
LogFile = AppConfiguration.LogFilePath+"WAP"+sErrorTime + ".log";
if(!File.Exists(LogFile))
{
File.Create(LogFile);
}
}
public void closeStream()
{
if(sw != null)
{
sw.Close();
}
}
public void LogException(string className,string methodName, string errorMessage)
{
try
{
if(!File.Exists(LogFile))
{
File.Create(LogFile);
}
sw = new StreamWriter(LogFile,true);
sw.WriteLine(DateTime.Now.ToString() + " | " + className + ":" + methodName + ":"+ errorMessage);
sw.Flush();
sw.Close();
}
catch(Exception)
{
if(sw != null)
{
sw.Close();
}
}
}
Rather than opening and closing the log file for every entry, you might consider having a single logging process (e.g. syslog or a separate logging thread) that keeps the log file open.
Writing lines to a plain text file will mess it up if multiple users are going to handle it. Rather, you can use database to store / retrieve text. You can even provide a button somewhere to export the records to a plain text file if needed.

Webtest with session-id in url

We have an ASP.Net site that redirects you to a url that shows a session-id. like this:
http://localhost/(S(f3rjcw45q4cqarboeme53lbx))/main.aspx
This id is unique with every request.
Is it possible to test this site using a standard visual studio 2008/2010 webtest? How can I provide the test this data?
I have to call a couple of different pages using that same id.
Yes, it is relatively easy to do this. You will need to create a coded webtest however.
In my example we have a login post that will return the url including the session string.
Just after the we yield the login post request (request3) to the enumerator I call the following.
WebTestRequest request3 = new WebTestRequest((this.Context["WebServer1"].ToString() + "/ICS/Login/English/Login.aspx"));
//more request setup code removed for clarity
yield return request3;
string responseUrl = Context.LastResponse.ResponseUri.AbsoluteUri;
string cookieUrl = GetUrlCookie(responseUrl, this.Context["WebServer1"].ToString(),"/main.aspx");
request3 = null;
Where GetUrlCookie is something like this:
public static string GetUrlCookie(string fullUrl, string webServerUrl, string afterUrlPArt)
{
string result = fullUrl.Substring(webServerUrl.Length);
result = result.Substring(0, result.Length - afterUrlPArt.Length);
return result;
}
Once you have the session cookie string, you can substitute it really easy in any subsequent urls for request/post
e.g.
WebTestRequest request4 = new WebTestRequest((this.Context["WebServer1"].ToString() + cookieUrl + "/mySecureForm.aspx"));
I apologise for my code being so rough, but it was deprecated in my project and is pulled from the first version of the codebase - and for saying it was easy :)
For any load testing, depending on your application, you may have to come up with a stored procedure to call to provide distinct login information each time the test is run.
Note, because the response url cannot be determined ahead of time, for the login post you will have to temporarily turn off the urlValidationEventHandler. To do this I store the validationruleeventhandler in a local variable:
ValidateResponseUrl validationRule1 = new ValidateResponseUrl();
urlValidationRuleEventHandler = new EventHandler<ValidationEventArgs>(validationRule1.Validate);
So can then turn it on and off as I require:
this.ValidateResponse -= urlValidationRuleEventHandler ;
this.ValidateResponse += urlValidationRuleEventHandler ;
The alternative is to code your own such as this (reflectored from the Visual Studio code and changed to be case insensitive.
class QueryLessCaseInsensitiveValidateResponseUrl : ValidateResponseUrl
{
public override void Validate(object sender, ValidationEventArgs e)
{
Uri uri;
string uriString = string.IsNullOrEmpty(e.Request.ExpectedResponseUrl) ? e.Request.Url : e.Request.ExpectedResponseUrl;
if (!Uri.TryCreate(e.Request.Url, UriKind.Absolute, out uri))
{
e.Message = "The request URL could not be parsed";
e.IsValid = false;
}
else
{
Uri uri2;
string leftPart = uri.GetLeftPart(UriPartial.Path);
if (!Uri.TryCreate(uriString, UriKind.Absolute, out uri2))
{
e.Message = "The request URL could not be parsed";
e.IsValid = false;
}
else
{
uriString = uri2.GetLeftPart(UriPartial.Path);
////this removes the query string
//uriString.Substring(0, uriString.Length - uri2.Query.Length);
Uri uritemp = new Uri(uriString);
if (uritemp.Query.Length > 0)
{
string fred = "There is a problem";
}
//changed to ignore case
if (string.Equals(leftPart, uriString, StringComparison.OrdinalIgnoreCase))
{
e.IsValid = true;
}
else
{
e.Message = string.Format("The value of the ExpectedResponseUrl property '{0}' does not equal the actual response URL '{1}'. QueryString parameters were ignored.", new object[] { uriString, leftPart });
e.IsValid = false;
}
}
}
}
}

Resources