Suppose that I printed some documents from a program like MS Word. Let's say I selected 4 documents at once, so three of them would end up waiting in the printer queue. I would like to access and read some information about the documents waiting in the queue. In other words, how can I access the printer queue and read information about any pending files with java?
Is there a way to do that? If so, how can I do it?
Thanks for the help
maybe this function helpful for you.
public Integer getExistQueuePrinter() {
int queue = 0;
PrintService myService = null;
PrintService printService = PrintServiceLookup.lookupDefaultPrintService();
if (printService != null) {
//--> set printService.
myService = printService;
//--> get attributes from printService.
AttributeSet attributes = printService.getAttributes();
//--> loop attributes.
for (Attribute a : attributes.toArray()) {
String name = a.getName();
String value = attributes.get(a.getClass()).toString();
//System.out.println(name + " : " + value);
if (name.equals("queued-job-count")) {
//System.out.println(name + " : " + value);
queue = Integer.parseInt(value);
}
}
Object[] obj = attributes.toArray();
//System.out.println("queue = " + obj[3]);
return queue;
/* debug.
for (Object value : obj) {
System.out.println("Color = " + value);
}
*/
}
return null;
}
Here you can find complete code for accessing printer through java code.
it provides functionality like
cancel print job,
display print dialog,
print file etc..
http://anonsvn.icesoft.org//repo/icepdf/tags/icepdf-3.1.0/icepdf/viewer/src/org/icepdf/ri/common/PrintHelper.java
Related
I want to wait until my processes finish before I return my speechlet response, otherwise it seems to cut my process off and thus, not complete it, I actually believe it may freeze the process, but thats not my desire.
How do I go about waiting?
#Override
public SpeechletResponse onIntent(SpeechletRequestEnvelope<IntentRequest> requestEnvelope) {
IntentRequest request = requestEnvelope.getRequest();
Intent intent = request.getIntent();
String intentName = (intent != null) ? intent.getName() : null;
if (intentName == null) return null;
switch (intentName) {
case IntentTitle.NEW_TICKET:
switch (request.getDialogState()) {
case STARTED:
return Response.getDialogueResponse(intent, true);
case IN_PROGRESS:
return Response.getDialogueResponse(intent, false);
case COMPLETED:
String numberString = intent.getSlot(SlotTitle.ID).getValue();
if (!NumberUtils.isCreatable(numberString)) return Response.ERROR;
Member member = Info.GUILD.getMemberById(numberString);
User sender = UserDB.getUser(member);
CommissionTicket commissionTicket = new CommissionTicket(sender);
commissionTicket.create();
//wait until processes finish before continuing
return Response.NEW_TICKED_CREATED;
}
}
return null;
}
UPDATE:
Had a look at the CloudWatch logs, and well, pretty much what I expected was happening is happening... have a look at the times for these logs (I ran them 3 different times, so 3 different times are logged, but apart of the same lambda session)
public void create() {
System.out.println("log2");
GuildController guildController = Info.GUILD.getController();
guildController.createTextChannel(ticketType.name().toLowerCase() + "-" + creator.getName() + "-" + id.value()).queue(channel -> {
System.out.println("log3");
ChannelManager channelManager = channel.getManager();
GuildManager guildManager = channelManager.getGuild().getManager();
List<Member> members = guildManager.getGuild().getMembers();
List<Member> admins = new ArrayList<>();
for (Member member : members) {
for (Role role : member.getRoles()) {
if (!role.getName().equalsIgnoreCase(Info.ADMIN_STRING)) continue;
admins.add(member);
}
}
System.out.println("log4");
for (Member member : members) {
if (member.equals(creator.getMember())) continue;
channel.createPermissionOverride(member).setDeny(Permission.MESSAGE_READ).queue();
}
System.out.println("log5");
for (Member admin : admins) {
if (admin.equals(creator.getMember())) continue;
channel.createPermissionOverride(admin).setAllow(Permission.MESSAGE_READ).queue();
}
System.out.println("log6");
BotMessage botMessage = new BotMessage();
botMessage
.setTitle("New Ticket! User: " + creator.getName())
.setColour(Color.CYAN)
.setDescription("Please enter your full request here! \n" +
"Make sure to let us know whether you are looking for a quote/timeframe,\n" +
"or have a budget in mind, and we will work around you!\n\n" +
"A sales representative will be with you as soon as possible!")
.send((TextChannel) channel);
System.out.println("log7");
this.textChannel = (TextChannel) channel;
TicketDB.addTicket(this);
System.out.println("log8");
}
);
Logs:
https://gyazo.com/0ad2baa8d1438be8364dd1112159c4f4
https://gyazo.com/e197f33335046afe3c9f8f1ace267d30
UPDATE
Implemented the Future class, worked, but still a bit buggy.
It now completely creates the ticket, which is great, however, when I go to send the same call again, it for some reason sends a message in the same channel before preceding to create the next ticket.
So, to simulate...
Function call through AWS Lambda
Creates ticket completely
Function call through AWS Lambda again
Sends a message or two in the previous tickets channel
Creates new ticket completely
https://gyazo.com/dc6e4391f4964f41a73f1c3be92190f9
#Override
public SpeechletResponse onIntent(SpeechletRequestEnvelope<IntentRequest> requestEnvelope) {
IntentRequest request = requestEnvelope.getRequest();
Intent intent = request.getIntent();
String intentName = (intent != null) ? intent.getName() : null;
if (intentName == null) return null;
switch (intentName) {
case IntentTitle.NEW_TICKET:
switch (request.getDialogState()) {
case STARTED:
return Response.getDialogueResponse(intent, true);
case IN_PROGRESS:
return Response.getDialogueResponse(intent, false);
case COMPLETED:
String numberString = intent.getSlot(SlotTitle.ID).getValue();
if (!NumberUtils.isCreatable(numberString)) return Response.ERROR;
Member member = Info.GUILD.getMemberById(numberString);
User sender = UserDB.getUser(member);
System.out.println("log1");
Future<Ticket> commissionTicket = new CommissionTicket(sender).create();
try {
commissionTicket.get(10000, TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrace();
}
//wait until processes finish before continuing
return Response.NEW_TICKED_CREATED;
}
}
return null;
}
In the Ticket class:
public Future<Ticket> create() {
System.out.println("log2");
GuildController guildController = Info.GUILD.getController();
RequestFuture<Channel> channelRequestFuture = guildController.createTextChannel(ticketType.name().toLowerCase() + "-" + creator.getName() + "-" + id.value()).submit();
try {
Channel channel = channelRequestFuture.get(10000, TimeUnit.MILLISECONDS);
System.out.println("log3");
ChannelManager channelManager = channel.getManager();
GuildManager guildManager = channelManager.getGuild().getManager();
List<Member> members = guildManager.getGuild().getMembers();
List<Member> admins = new ArrayList<>();
for (Member member : members) {
for (Role role : member.getRoles()) {
if (!role.getName().equalsIgnoreCase(Info.ADMIN_STRING)) continue;
admins.add(member);
}
}
System.out.println("log4");
for (Member member : members) {
if (member.equals(creator.getMember())) continue;
channel.createPermissionOverride(member).setDeny(Permission.MESSAGE_READ).queue();
}
System.out.println("log5");
for (Member admin : admins) {
if (admin.equals(creator.getMember())) continue;
channel.createPermissionOverride(admin).setAllow(Permission.MESSAGE_READ).queue();
}
System.out.println("log6");
BotMessage botMessage = new BotMessage();
botMessage
.setTitle("New Ticket! User: " + creator.getName())
.setColour(Color.CYAN)
.setDescription("Please enter your full request here! \n" +
"Make sure to let us know whether you are looking for a quote/timeframe,\n" +
"or have a budget in mind, and we will work around you!\n\n" +
"A sales representative will be with you as soon as possible!")
.send((TextChannel) channel);
System.out.println("log7");
this.textChannel = (TextChannel) channel;
TicketDB.addTicket(this);
System.out.println("log8");
Future<Ticket> future = ConcurrentUtils.constantFuture(this);
return future;
} catch (Exception e) {
e.printStackTrace();
}
if (!userIsInTicket(creator)) users.add(creator);
return null;
}
I'm not sure what's going on inside commissionTicket.create(); (I assume it's your code, not part of some library, and that it's running asynchronously somehow), but one solution would be to have that method return a Future<> object and then wait on it to finish. Something along the lines of:
Future<CommissionTicket> commissionTicketFuture = CommissionTicket.create(sender);
commissionTicketFuture.get(SOME_TIMEOUT, TimeUnit.MILLIS);
return Response.NEW_TICKET_CREATED;
I'm using Java to download HTML contents of websites whose URLs are stored in a database. I'd like to put their HTML into database, too.
I'm using Jsoup for this purpose:
public String downloadHTML(String byLink) {
String htmlInPage = "";
try {
Document doc = Jsoup.connect(byLink).get();
htmlInPage = doc.html();
} catch (org.jsoup.UnsupportedMimeTypeException e) {
// process this and some other exceptions
}
return htmlInPage;
}
I'd like to download websites concurrently and use this function:
public void downloadURL(int websiteId, String url,
String categoryName, ExecutorService executorService) {
executorService.submit((Runnable) () -> {
String htmlInPage = downloadHTML(url);
System.out.println("Category: " + categoryName + " " + websiteId + " " + url);
String insertQuery =
"INSERT INTO html_data (website_id, html_contents) VALUES (?,?)";
dbUtils.query(insertQuery, websiteId, htmlInPage);
});
}
dbUtils is my class based on Apache Commons DbUtils. Details are here: http://pastebin.com/iAKXchbQ
And I'm using everything mentioned above in a such way: (List<Object[]> details are explained on pastebin, too)
public static void main(String[] args) {
DbUtils dbUtils = new DbUtils("host", "db", "driver", "user", "pass");
List<String> categoriesList =
Arrays.asList("weapons", "planes", "cooking", "manga");
String sql = "SELECT lw.id, lw.website_url, category_name " +
"FROM list_of_websites AS lw JOIN list_of_categories AS lc " +
"ON lw.category_id = lc.id " +
"where category_name = ? ";
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (String category : categoriesList) {
List<Object[]> sitesInCategory = dbUtils.select(sql, category );
for (Object[] entry : sitesInCategory) {
int websiteId = (int) entry[0];
String url = (String) entry[1];
String categoryName = (String) entry[2];
downloadURL(websiteId, url, categoryName, executorService);
}
}
executorService.shutdown();
}
I'm not sure if this solution is correct but it works. Now I want to modify code to save HTML not from all websites in my database, but only their fixed ammount in each category.
For example, download and save HTML of 50 websites from the "weapons" category, 50 from "planes", etc. I don't think it's necessary to use sql for this purpose: if we select 50 sites per category, it doesn't mean we save them all, because of possibly incorrect syntax and connection problems.
I've tryed to create separate class implementing Runnable with fields: counter and maxWebsitesPerCategory, but these variables aren't updated. Another idea was to create field Map<String,Integer> sitesInCategory instead of counter, put each category as a key there and increment its value until it reaches maxWebsitesPerCategory, but it didn't work, too. Please, help me!
P.S: I'll also be grateful for any recommendations connected with my realization of concurrent downloading (I haven't worked with concurrency in Java before and this is my first attempt)
How about this?
for (String category : categoriesList) {
dbUtils.select(sql, category).stream()
.limit(50)
.forEach(entry -> {
int websiteId = (int) entry[0];
String url = (String) entry[1];
String categoryName = (String) entry[2];
downloadURL(websiteId, url, categoryName, executorService);
});
}
sitesInCategory has been replaced with a stream of at most 50 elements, then your code is run on each entry.
EDIT
In regard to comments. I've gone ahead and restructured a bit, you can modify/implement the content of the methods I've suggested.
public void werk(Queue<Object[]> q, ExecutorService executorService) {
executorService.submit(() -> {
try {
Object[] o = q.remove();
try {
String html = downloadHTML(o); // this takes one of your object arrays and returns the text of an html page
insertIntoDB(html); // this is the code in the latter half of your downloadURL method
}catch (/*narrow exception type indicating download failure*/Exception e) {
werk(q, executorService);
}
}catch (NoSuchElementException e) {}
});
}
^^^ This method does most of the work.
for (String category : categoriesList) {
Queue<Object[]> q = new ConcurrentLinkedQueue<>(dbUtils.select(sql, category));
IntStream.range(0, 50).forEach(i -> werk(q, executorService));
}
^^^ this is the for loop in your main
Now each category tries to download 50 pages, upon failure of downloading a page it moves on and tries to download another page. In this way, you will either download 50 pages or have attempted to download all pages in the category.
I am working on an Android application which uses Xerces for Iteration. I have a custom method which is called to store a filtered set of data values in it after being iterated through via a while loop. Part of the specific while loop is as follows:
while((n = iterator.nextNode())!= null) {
... //other code
object.customMethod(tagName, n.getNodeValue()); //occurs only once per iteration
Log.i("TAG", tagName + ": " + n.getNodeValue())
...//other code
}
The customMethod received a key and value pair and saves them as Strings using Android's SharedPreferences system. At the moment of being called, the method actually has the key=>value pair, but it appears the method is being called more than once during the same iteration loop. I came to know this after printing out the logcat sample showing the output after each call within customMethod due to having blanks/nulls saved in the preferences when I fetched them later. Why is this happening? A sample output is as shown:
TAG inserted: 500.00 //log call right after insertion within customMethod()
TAG vc:limit: 500.00 //log call after returning from customMethod()
TAG inserted:
TAG inserted:
TAG inserted: //other calls, which I want to know how and why they are occurring
All the above occurred during a single iteration of the while loop. Anyone know why this is happening? Something else, it seems the code right after the insertion only runs once, but only the code within the customMethod() gets called several times during the iteration. The custom method is as shown below:
public boolean customMethod(String key, String val) {
boolean inserted = prefs.edit().putString(key, val).commit(); //prefs is global
Log.i("TAG", (inserted == true ? "inserted: " + val : "not inserted"));
return inserted;
}
Edit: The full while loop as requested:
private void setSelectedID(int pos)
{
...
String id = IDs[pos];
...
NodeList descElements = MainActivity.root.getElementsByTagName(VCard.DIRECTORY); //DIRECTORY is a String constant
Element desc = (Element) descElements.item(0);
NodeIterator iterator = ((DocumentTraversal)MainActivity.doc).createNodeIterator(desc, NodeFilter.SHOW_ALL, null, true);
Node n;
VCard object = new VCard(this);
while((n = iterator.nextNode())!= null)
{
if(n.getNodeType() == Node.CDATA_SECTION_NODE || n.getNodeType() == Node.TEXT_NODE)
{
String tagName = n.getParentNode().getNodeName();
if(object.containsKey(tagName))
{
Element e = (Element) n.getParentNode();
if(e.hasAttribute("id") && e.getAttribute("id").equals(id))
{
object.customMethod(tagName, n.getNodeValue());
Log.i("TAG", tagName + ": " + n.getNodeValue())
}
}
}
}
}
I'm following this tutorial to write a workflow for 3 HTML forms (without using CQ5 form component and CQ5 workflow submit button). I use this code to write Process step handling for my workflow:
public class MyProcess implements WorkflowProcess {
public void execute(WorkItem item, WorkflowSession session,
MetaDataMap map) throws WorkflowException {
boolean advanced = false;
Boolean goBack = map.get("goBack", Boolean.class);
List<Route> routes = null;
if (goBack == null || goBack == false) {
routes = session.getRoutes(item);
} else {
routes = session.getBackRoutes(item);
}
for (Route route : routes) {
LOG.info("===============================");
LOG.info("Rout name: " + route.getName());
LOG.info("Destinations: ");
for (WorkflowTransition dest: route.getDestinations()) {
LOG.info("dest: " + dest.getTo().getTitle());
}
LOG.info("===============================");
if (route.hasDefault()) {
String fromTitle = item.getNode().getTitle();
String toTitle = route.getDestinations().get(0).getTo()
.getTitle();
session.complete(item, route);
LOG.info("===============================");
LOG.info(item.getId() + " advanced from " + fromTitle
+ " to " + toTitle);
LOG.info("===============================");
advanced = true;
}
}
// fallback if no route was marked as default
if (!advanced) {
session.complete(item, routes.get(0));
String fromTitle = item.getNode().getTitle();
String toTitle = routes.get(0).getDestinations().get(0).getTo()
.getTitle();
LOG.info("===============================");
LOG.info(item.getId() + " advanced from " + fromTitle + " to "
+ toTitle);
LOG.info("===============================");
}
}
}
My question is: after i use session.complete to advance to next step, how can i refresh the workflow session to reach the current step information.
I think #yashahuja is correct. I was poking around and on the aem 'working with workflow' page I found some information about persisting data throw workflow steps using MetaDataMap.
From this page: http://dev.day.com/docs/en/cq/current/workflows/wf-extending.html
"Use workflow metadata to persist information that is required during the lifetime of the workflow. A common requirement of workflow steps is to persist data for future use in the workflow, or to retrieve the persisted data.
Workflow metadata is stored in a MetaDataMap object. The Java API provides the Workflow.getMetaDataMap method that returns the MetaDataMap object. Also, the WorkItem.getWorkflowData method returns a WorkflowData object that provides the same getMetaDataMap object.
Therefore, the workflow MetaDataMap object is available to the OSGi service or ECMA script of a step component."
example:
public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) throws WorkflowException {
MetaDataMap wfd = item.getWorkflow().getMetaDataMap();
wfd.put("mykey", "My Step Value");
Set<String> keyset = wfd.keySet();
Iterator<String> i = keyset.iterator();
while (i.hasNext()){
Object key = i.next();
log.info("The workflow medata includes key {} and value {}",key.toString(),wfd.get(key).toString());
}
I use OpenCmis in-memory for testing. But when I create a document I am not allowed to set the versioningState to something else then versioningState.NONE.
The doc created is not versionable some way... I used the code from http://chemistry.apache.org/java/examples/example-create-update.html
The test method:
public void test() {
String filename = "test123";
Folder folder = this.session.getRootFolder();
// Create a doc
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document");
properties.put(PropertyIds.NAME, filename);
String docText = "This is a sample document";
byte[] content = docText.getBytes();
InputStream stream = new ByteArrayInputStream(content);
ContentStream contentStream = this.session.getObjectFactory().createContentStream(filename, Long.valueOf(content.length), "text/plain", stream);
Document doc = folder.createDocument(
properties,
contentStream,
VersioningState.MAJOR);
}
The exception I get:
org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException: The versioning state flag is imcompatible to the type definition.
What am I missing?
I found the reason...
By executing the following code I discovered that the OBJECT_TYPE_ID 'cmis:document' don't allow versioning.
Code to view all available OBJECT_TYPE_ID's (source):
boolean includePropertyDefintions = true;
for (t in session.getTypeDescendants(
null, // start at the top of the tree
-1, // infinite depth recursion
includePropertyDefintions // include prop defs
)) {
printTypes(t, "");
}
static void printTypes(Tree tree, String tab) {
ObjectType objType = tree.getItem();
println(tab + "TYPE:" + objType.getDisplayName() +
" (" + objType.getDescription() + ")");
// Print some of the common attributes for this type
print(tab + " Id:" + objType.getId());
print(" Fileable:" + objType.isFileable());
print(" Queryable:" + objType.isQueryable());
if (objType instanceof DocumentType) {
print(" [DOC Attrs->] Versionable:" +
((DocumentType)objType).isVersionable());
print(" Content:" +
((DocumentType)objType).getContentStreamAllowed());
}
println(""); // end the line
for (t in tree.getChildren()) {
// there are more - call self for next level
printTypes(t, tab + " ");
}
}
This resulted in a list like this:
TYPE:CMIS Folder (Description of CMIS Folder Type) Id:cmis:folder
Fileable:true Queryable:true
TYPE:CMIS Document (Description of CMIS Document Type)
Id:cmis:document Fileable:true Queryable:true [DOC Attrs->]
Versionable:false Content:ALLOWED
TYPE:My Type 1 Level 1 (Description of My Type 1 Level 1 Type)
Id:MyDocType1 Fileable:true Queryable:true [DOC Attrs->]
Versionable:false Content:ALLOWED
TYPE:VersionedType (Description of VersionedType Type)
Id:VersionableType Fileable:true Queryable:true [DOC Attrs->]
Versionable:true Content:ALLOWED
As you can see the last OBJECT_TYPE_ID has versionable: true... and when I use that it does work.