I have a hibernate class that requires 3 different sessions. It currently uses 2 sessions and works perfectly. The first session is used to read data from an external db. The second session is used to save data to our internal db. I'm adding a third session because, we need to keep track on the transaction regardless of whether or not the main transaction is successful (the XXXXUpdate object). My problem is that the new session is hanging on tx.commit().
private synchronized void executeUpdate(Long manualUpdateTagIndex) throws Exception {
LogPersistenceLoggingContext ctx = new LogPersistenceThreadContext().getLogPersistenceLoggingContext();
DateTime minTriggerDate = parseDateTimeIfNotNull(minTriggerTime);
DateTime maxTriggerDate = parseDateTimeIfNotNull(maxTriggerTime);
Session webdataSession = null;
Session XXXXUpdateSession = null;
XXXXUpdate update = new XXXXUpdate();
update.setExecutedAt(new DateTime());
update.setStatus(WebdataUpdateStatus.Success);
boolean commit = true;
int tagCount = 0;
List<Period> tagPeriods = new ArrayList<>();
Map<Long, DateTime> tagIndexes = new LinkedHashMap<>();
try {
XXXXUpdateSession = accountingService.openUnmanagedSession();
XXXXUpdateSession.getTransaction().begin();
XXXXUpdateSession.save(update);
HierarchicalLogContext logCtx = new HierarchicalLogContext(String.valueOf(update.getId()));
ctx.pushLoggingContext(logCtx);
ctx.log(logger, Level.INFO, new XXXXLogMarker(), "Executing XXXX data transfer", new Object[]{});
if (webdataSessionFactory == null){
throw new Exception("Failed to obtain webdata session factory. See earlier log entries");
}
try {
webdataSession = webdataSessionFactory.openSession();
} catch (Exception ex) {
update.setStatus(WebdataUpdateStatus.ConnectionError);
throw new Exception("Failed to obtain webdata connection", ex);
}
webdataSession.getTransaction().begin();
if (manualUpdateTagIndex == null) { // automatic tags update
XXXXUpdate lastUpdate = (XXXXUpdate) HibernateUtil.getCurrentSpringManagedSession()
.createCriteria(XXXXUpdate.class)
.add(Restrictions.isNotNull("latestTriggerTimestamp"))
.add(Restrictions.eq("status", WebdataUpdateStatus.Success))
.add(Restrictions.eq("manualUpdate", false))
.addOrder(Order.desc("latestTriggerTimestamp"))
.setMaxResults(1).uniqueResult();
DateTime lastUpdatedDate = Period.defaultEffectiveInstant;
if (minTriggerDate != null) {
lastUpdatedDate = minTriggerDate;
}
if (lastUpdate != null && lastUpdate.getLatestTriggerTimestamp() != null) {
lastUpdatedDate = lastUpdate.getLatestTriggerTimestamp();
ctx.log(logger, Level.INFO, new XXXXLogMarker(),
"Querying for tag event triggers newer than last update timestamp [" + lastUpdate.getLatestTriggerTimestamp() + "]", new Object[]{});
} else {
ctx.log(logger, Level.INFO, new XXXXLogMarker(), "Update has never run. Catching up with history", new Object[]{});
}
#SuppressWarnings("unchecked")
List<XXXXProcessedTagRequest> processedReqs = HibernateUtil.getCurrentSpringManagedSession()
.createCriteria(XXXXProcessedTagRequest.class).list();
Query triggerQuery = webdataSession.createQuery(
"select trigger, "
+ "trigger.TagIndex,"
+ "req "
+ "from XXXXTagEventTrigger as trigger "
+ "join trigger.req as req "
+ "where trigger.EventType in (:eventTypes) "
+ "and trigger.timestamp > :lastUpdateMinusDelta "
+ (maxTriggerDate != null?"and trigger.timestamp < :maxDate ":"")
+ "and req.CurrentState = :currentState "
+ "order by trigger.timestamp,trigger.reqIndex");
triggerQuery.setParameterList("eventTypes", new Object[]{5, 9});
triggerQuery.setParameter("lastUpdateMinusDelta", lastUpdatedDate.minusHours(hoursToKeepProcessedReqs) );
if (maxTriggerDate != null){
triggerQuery.setParameter("maxDate", maxTriggerDate);
}
triggerQuery.setParameter("currentState", 2);
#SuppressWarnings("unchecked")
List<Object[]> allTriggers = triggerQuery.list();
List<Object[]> unprocessedTriggers = removeProcessedTags(new ArrayList<Object[]>(allTriggers),processedReqs,ctx);
for (Object[] row : unprocessedTriggers) {
XXXXTagEventTrigger trigger = (XXXXTagEventTrigger) row[0];
if (lastUpdatedDate == null || lastUpdatedDate.isBefore(trigger.getTimestamp().getMillis())) {
lastUpdatedDate = new DateTime(trigger.getTimestamp());
}
tagIndexes.put((Long) row[1], new DateTime(trigger.getTimestamp()));
XXXXProcessedTagRequest processedReq = new XXXXProcessedTagRequest();
processedReq.setReqIndex(((XXXXTagReq)row[2]).getReqIndex());
processedReq.setTimestamp(trigger.getTimestamp());
HibernateUtil.getCurrentSpringManagedSession().save(processedReq);
}
ctx.log(logger, Level.INFO, new XXXXLogMarker(),
"Found [" + unprocessedTriggers.size() + "] tag event triggers on [" + tagIndexes.size() + "] tags", new Object[]{});
update.setLatestTriggerTimestamp(lastUpdatedDate);
} else { // manual tag update
ctx.log(logger, Level.INFO, new XXXXLogMarker(), "Executing manual update for tag index [" + manualUpdateTagIndex + "]", new Object[]{});
DateTime now = new DateTime();
tagIndexes.put(manualUpdateTagIndex, now);
update.setLatestTriggerTimestamp(now);
update.setManualUpdate(true);
}
if (tagIndexes.size() > 0) {
int totalTagCount = tagIndexes.size();
while (!tagIndexes.isEmpty()) {
List<Long> batchIndexes = new ArrayList<>();
Iterator<Map.Entry<Long, DateTime>> indexIt = tagIndexes.entrySet().iterator();
while (indexIt.hasNext() && batchIndexes.size() < tagBatchSize) {
batchIndexes.add(indexIt.next().getKey());
indexIt.remove();
}
Map<Long, LocalTag> existingTags = new HashMap<>();
#SuppressWarnings("unchecked")
List<LocalTag> existingTagIds = HibernateUtil.getCurrentSpringManagedSession()
.createCriteria(LocalTag.class)
.add(Restrictions.in("tagIndex", batchIndexes))
.add(Restrictions.eq("currentVersion", true)).list();
for (LocalTag lt : existingTagIds) {
existingTags.put(lt.getTagIndex(), lt);
}
ctx.log(logger, Level.INFO, new XXXXLogMarker(),
"Processing tag updates [" + tagCount + "-" + (tagCount + batchIndexes.size()) + "] of [" + totalTagCount + "]", new Object[]{});
Criteria tagCriteria = webdataSession.createCriteria(XXXXTag.class);
tagCriteria.add(Restrictions.in("TagIndex", batchIndexes));
if (!includeTestTags) {
tagCriteria.add(Restrictions.eq("TestTag", "0"));
}
tagCriteria.setFetchMode("XXXXTagMS", FetchMode.JOIN);
tagCriteria.setFetchMode("XXXXTagPS", FetchMode.JOIN);
tagCriteria.setFetchMode("XXXXTagCCList", FetchMode.JOIN);
tagCriteria.setFetchMode("XXXXTagTA", FetchMode.JOIN);
tagCriteria.setFetchMode("XXXXTagCP", FetchMode.JOIN);
tagCriteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
#SuppressWarnings("unchecked")
List<XXXXTag> tags = tagCriteria.list();
if (manualUpdateTagIndex != null && tags.isEmpty()) {
throw new ValidationException("No tag found for manual update tag index [" + manualUpdateTagIndex + "]");
}
for (XXXXTag tag : tags) {
update.getProcessedTags().add(updateTag(tag, tagIndexes.get(tag.getTagIndex()), existingTags));
tagCount++;
if (fireEventLastActions.contains(tag.getLastAction().trim())) {
tagPeriods.add(new Period(tag.getStartTime().getMillis(), tag.getStopTime().getMillis()));
}
}
HibernateUtil.getCurrentSpringManagedSession().flush();
HibernateUtil.getCurrentSpringManagedSession().clear();
webdataSession.clear();
}
} else {
ctx.log(logger, Level.INFO, new XXXXLogMarker(), "No updates found", new Object[]{});
}
HibernateUtil.getCurrentSpringManagedSession()
.createQuery("delete XXXXUpdate where executedAt < :purgeDate")
.setParameter("purgeDate", new DateTime().minusDays(daysToKeepUpdateHistory))
.executeUpdate();
HibernateUtil.getCurrentSpringManagedSession()
.createQuery("delete XXXXProcessedTagRequest where timestamp < :purgeDate")
.setParameter("purgeDate", new DateTime().minusHours(hoursToKeepProcessedReqs))
.executeUpdate();
update.setStatus(WebdataUpdateStatus.Success);
update.setTagCount(update.getProcessedTags().size());
tagPeriods = Period.merge(tagPeriods);
for (Period p : tagPeriods) {
XXXXUpdatePeriod oup = new XXXXUpdatePeriod();
oup.setXXXXUpdate(update);
oup.setStartDate(p.getStart());
oup.setEndDate(p.getEnd());
update.getPeriods().add(oup);
}
HibernateUtil.getCurrentSpringManagedSession().flush();
ctx.log(logger, Level.INFO, new XXXXLogMarker(), "XXXX data transfer complete. Transferred [" + tagCount + "] tag updates", new Object[]{});
ctx.popLoggingContext(logCtx);
} catch (Exception ex) {
HibernateUtil.getCurrentSpringManagedSession().clear();
update.getProcessedTags().clear();
update.setTagCount(0);
update.setStatus(WebdataUpdateStatus.TransferError);
commit = false;
ctx.log(logger, Level.ERROR, new XXXXLogMarker(), "XXXX data transfer failed", new Object[]{}, ex);
throw new Exception("XXXX data transfer failed", ex);
} finally {
try {
XXXXUpdateSession.saveOrUpdate(update);
XXXXUpdateSession.getTransaction().commit();
} catch (Exception ex) {
commit = false;
ctx.log(logger, Level.ERROR, new XXXXLogMarker(), "Failed to save XXXX transfer update record", new Object[]{}, ex);
throw new Exception("Failed to save XXXX transfer update record", ex);
} finally {
if (!commit) {
webdataSession.getTransaction().rollback();
} else {
webdataSession.getTransaction().commit();
}
ResourceDisposer.dispose(webdataSession);
}
}
}
The new session is the XXXXUpdateSession. The only new code is that which is related to this session. It's some kind of timing issue because, when I use hibernate debug logging, the tx commits without issue. It also commits when I attempt to debug the hibernate commit(). I do not have much experience with hibernate so, I'm probably missing something obvious. Any help would be greatly appreciated. Thanks.
You have opened two transactions webdataSession.getTransaction().begin(); which is causing the issue (20 & 37 lines in the above code).
You can open the second transaction after committing the first transaction.
Also, it is not a best practice to have long methods like which will be very hard to debug the issues and become the nightmare for maintenance/support of the project.
Related
I have an inherited project, a BMC Remedy application and never worked with this Remedy stuff. This project modifies Incidents and Work Orders from remedy through the Remedy API. I have literally no idea on this.
There's a process that closes incidents that are in resolved state and have not been modified in the last 36 hours. Sometimes, those incidents have the 'categorization' field empty, and the client wants to fill this categorization before closing it.
This is part of the code:
Connection to Remedy:
public static void main(String args[]) {
// Inicializamos el logger
java.util.logging.LogManager.getLogManager().reset();
try {
// Nos conectamos a Remedy y a MySQL
LOGGER.info("Conectando a bases de datos");
if (!connect()) {
throw new Exception("Fallo al conectar a Remedy o a MySQL");
}
// Metodo para cerrar incidecias resueltas
remedy.cerrarIncidencias(sql.queryResueltas36h());
// Desconectamos de Remedy y MySQL
disconnect();
} catch (Exception e) {
LOGGER.error("Error critico: ", e);
try {
remedy.desconectar();
} catch (Exception e1) {
}
try {
sql.desconectar();
} catch (Exception e1) {
}
}
}
Function to closing incidents:
public void cerrarIncidencias(List<String> incs) throws Exception {
int contador = 1;
for (String inc : incs) {
try {
// Obtenemos la incidencia
QualifierInfo qual = server.parseQualification("HPD:Help Desk", "'Incident Number' = \"" + inc + "\"");
List<Entry> entries = server.getListEntryObjects("HPD:Help Desk", qual, 0, 0, null,
Constantes.CAMPOS_HPD_HELP_DESK_CERRAR_INCIDENCIA, false, null);
// Rellenamos un comentario generico
Entry comment = new Entry();
comment.put(Constantes.HPD_WORKLOG_DETAILED_DESCRIPTION, new Value("Cierre automatico tras 36 horas en resuelto."));
comment.put(Constantes.HPD_WORKLOG_INCIDENT_NUMBER, new Value(inc));
comment.put(Constantes.HPD_WORKLOG_DESCRIPTION, new Value("----"));
comment.put(Constantes.HPD_WORKLOG_WORKLOG_TYPE, new Value(8000));
for (Entry entry : entries) {
entry.put(Constantes.HPD_HELP_DESK_STATUS, new Value(5)); // Estado a cerrado
if (entry.get(Constantes.HPD_HELP_DESK_ASSIGNEE_LOGIN_ID).getValue() == null) {
entry.put(Constantes.HPD_HELP_DESK_ASSIGNEE_LOGIN_ID, new Value("lmoren70"));
entry.put(Constantes.HPD_HELP_DESK_ASSIGNEE, new Value("Luis Manuel Moreno Rodriguez")); // Usuario asignado
}
server.setEntry("HPD:Help Desk", entry.getEntryId(), entry, null, 0);
server.createEntry("HPD:WorkLog", comment);
LOGGER.info("Incidencia " + inc + " cerrada con exito - " + contador + " de " + incs.size());
}
} catch (Exception e) {
LOGGER.error("Incidencia " + inc + " NO se ha podido cerrar - " + contador + " de " + incs.size() + "\n"
+ e.getMessage());
}
contador++;
}
}
Query:
I thought to do an update directly to the database BUT this database reads from Remedy, so I have to update Remedy.
public List<String> queryResueltas36h() {
String query = "SELECT inc FROM vdf_tickets, vdf_groups WHERE status = 'Resuelto' AND LENGTH(inc) > 9 "
+ "AND vdf_groups.group = creator_group AND (vdf_groups.categorization = 'TES' OR vdf_groups.group IN ('TES', 'ARCA', 'NetOps TES Assurance')) "
+ "AND last_resolved_date < DATE_ADD(NOW(), INTERVAL -36 HOUR) ORDER BY inc DESC";
List<String> incs = new ArrayList<String>();
try {
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String inc = rs.getString("inc");
incs.add(inc);
}
stmt.close();
} catch (Exception e) {
LOGGER.error("Error al obtener lista de incidencias de la base de datos", e);
try {
stmt.close();
} catch (Exception e1) {
}
}
return incs;
}
What I want is to put the categorization to 'TES', in case there's no categorization.
One option I thought is to do an automation with Selenium and Python and not touching this code, but is far better to have all in the same project.
Any ideas? Thanks in advance!
You need to update your cerrarIncidencias function. But first you need to ask what categorisation you need to update.
There are three levels of categorisation.
Operational Categorisation
Product Categorisation
Resolution Categorisation
So decide which one you want to populate and get the field id for that field. For this example, I will say
Categorisation Tier 1 which is 1000000063
You'll need to add to CAMPOS_HPD_HELP_DESK_CATEGORISATION_TIER1=1000000063 to your Constantes file.
Then in your block
for (Entry entry : entries)
You need something like:
if (entry.get(Constantes.CAMPOS_HPD_HELP_DESK_CATEGORISATION_TIER1).getValue() == null) {
entry.put(Constantes.CAMPOS_HPD_HELP_DESK_CATEGORISATION_TIER1, new Value("Your Value for Categorisation Tier 1"));
}
I am facing a problem while trying to persist the existing stock in a preproduction environment.
What I am trying to do is actually to loop on a text file and insert substrings from that file into the database.
Here is the class that I execute :
public class RepriseStock {
private static Session session;
public RepriseStock() {
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
}
public static int insererPartenaires(String sCurrentLine, int i) {
String sql = "INSERT INTO PARTENAIRE(ID,"
+ "MVTSOC,"
+ " MVTAGR, "
+ "MVTNOMSOC,"
+ "MVTCPTTMAG,"
+ "DATEAGREMENT,"
+ "MVTCHAINE,"
+ "MVTRGPT,"
+ "MVTUNION,"
+ "MVTNOMMAG,"
+ "MVTTELSOC,"
+ "MVTADRMAG,"
+ "MVTVILMAG,"
+ "MVTMAIL,"
+ "MVTSITU)"
+ " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
Query query = session.createSQLQuery(sql);
query.setInteger(0, i);
query.setInteger(1, Integer.parseInt(sCurrentLine.substring(0, 3)));
query.setInteger(2, Integer.parseInt(sCurrentLine.substring(3, 10)));
query.setString(3, sCurrentLine.substring(10, 34));
query.setInteger(4, Integer.parseInt(sCurrentLine.substring(48, 53)));
query.setString(5, sCurrentLine.substring(77, 83));
query.setInteger(6, Integer.parseInt(sCurrentLine.substring(86, 90)));
query.setInteger(7, Integer.parseInt(sCurrentLine.substring(90, 94)));
// union
query.setInteger(8, Integer.parseInt(sCurrentLine.substring(94, 98)));
// enseigne 30
query.setString(9, sCurrentLine.substring(248, 278));
// tel
query.setString(10, sCurrentLine.substring(278, 293));
// adresse
query.setString(11, sCurrentLine.substring(293, 323));
// ville
query.setString(12, sCurrentLine.substring(323, 348));
// mail
query.setString(13, sCurrentLine.substring(398, 448));
// situ
query.setString(14, sCurrentLine.substring(449, 452));
return query.executeUpdate();
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Module de remplacement de méthode auto-généré
BufferedReader br = null;
RepriseStock rs = new RepriseStock();
try {
String sCurrentLine;
br = new BufferedReader(
new FileReader(
"C:\\Users\\test\\Desktop\\test\\reprise de stock\\nouveauFichierPREPROD.dat"));
int i = 0;
sCurrentLine = br.readLine();
while ((sCurrentLine = br.readLine()) != null) {
i++;
RepriseStock.insererPartenaires(sCurrentLine, i);
System.out.println("Nombre de fois : " + i);
}
System.out.println("total (" + i + " )");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)
br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
After the script is executed, i have the total of loops is 1022 times. But the data is not persisted into oracle table (Partenaire)
My log doesn't display any error.
Do you see the issue ?
It looks like you're not committing the transaction.
If you want each update to be a separate transaction, try moving session.beginTransaction(); to the beginning of the insererPartenaires method and capturing the Transaction object returned from that statement in a variable. Then, after each update, make sure to call commit() on the Transaction object.
If you want all of the updates to be the same transaction, move the beginTransaction() and commit() methods to surround the while loop in the main method.
Also just note that you're unnecessarily mixing static and non-static here. Try changing public static int insererPartenaires(String sCurrentLine, int i) to public int insererPartenaires(String sCurrentLine, int i). Then just use the instantiated RepriseStock object to call the method instead of invoking it statically.
You'll also need to change private static Session session to be private Session session
I'm not sure how the start and end date work with the whole find appointments. I am getting all the rooms for a public group, then getting the rooms for the group, then getting the appointments within a date range.
But the ranges act weird, I know there are appointments on 12-19 to 12-16, but if I set the start date range to 2013-10-10 and the end date to 2013-12-28, I get nothing.
If I set the end date to 2014-01-28, I get tons of stuff that is in the range previously mentioned. Why is that?
ExchangeService service = new ExchangeService();
ExchangeCredentials credentials = new WebCredentials( "username", "pw");
service.setCredentials( credentials );
service.setUrl( new URI("my mail url") );
Folder inbox = Folder.bind(service, WellKnownFolderName.Inbox);
System.out.println("messages: " + inbox.getTotalCount());
CalendarFolder cf = CalendarFolder.bind(service, WellKnownFolderName.Calendar);
//Get all new appts?
java.text.SimpleDateFormat formatter= new java.text.SimpleDateFormat("YYYY-mm-dd");
Date startDate1 = formatter.parse("2013-11-25");
Date endDate1 = formatter.parse("2014-01-28 ");
EmailAddressCollection myRoomLists = service.getRoomLists();
for (EmailAddress item : myRoomLists)
{
System.out.println("Room Email========"+ item.toString());
NameResolutionCollection nameResolutions = service.resolveName(
item.getName(),
ResolveNameSearchLocation.DirectoryOnly,
true);
for (NameResolution nameResolution : nameResolutions)
{
ExpandGroupResults groupResults;
//System.out.println(nameResolution.getMailbox().getAddress());
try {
groupResults = service.expandGroup(nameResolution.getMailbox().getAddress());
} catch (microsoft.exchange.webservices.data.ServiceResponseException e){
groupResults=null;
System.out.println("NO INFO FOR "+nameResolution.getMailbox().getAddress());
}
if (groupResults!=null){
for (EmailAddress member : groupResults.getMembers())
{
if (member.getAddress().indexOf("rm.Cary")>-1){
System.out.println(member.getName() + " <" + member.getAddress() + ">");
FolderId folderid = new FolderId(WellKnownFolderName.Calendar, new Mailbox(member.getAddress()));
try {
FindItemsResults<Appointment> aps = service.findAppointments(folderid, new CalendarView(startDate1,endDate1));
for (Item items : aps.getItems())
{
Appointment appt = (Appointment)items;
System.out.println("SUBJECT===== " + appt.getSubject());
System.out.println("Location======== " + appt.getLocation());
System.out.println("Start Time========" + appt.getStart());
System.out.println("End Time========"+appt.getEnd());
System.out.println("Email Address========"+ appt.getOrganizer().getAddress());
System.out.println("Last Modified Time========"+appt.getLastModifiedTime());
System.out.println("Start time========"+appt.getStart());
System.out.println("End Time========"+appt.getEnd());
System.out.println("Is recurring========"+appt.getIsRecurring());
System.out.println("Duration========"+appt.getDuration().toString());
System.out.println("Organizer========"+appt.getOrganizer());
System.out.println("Required Attendees========"+appt.getRequiredAttendees().getCount());
System.out.println("Optional Attendees========"+appt.getOptionalAttendees().getCount());
System.out.println("");
}
} catch (microsoft.exchange.webservices.data.ServiceResponseException e){
System.out.println(e.getMessage());
}
}
}
}
}
}
System.out.println("End");
Change it to:
java.text.SimpleDateFormat formatter= new java.text.SimpleDateFormat("yyyy-MM-dd");
I am trying to update nickname of a contact but not able to do so.
Below is the code which I have written
ArrayList<android.content.ContentProviderOperation> ops = new ArrayList<android.content.ContentProviderOperation>();
String selectArgs1 = Data.CONTACT_ID + " = ? AND " + Data.MIMETYPE + " = ? ";
String[] selectArgs2 = new String[]{ContactId, "vnd.android.cursor.item/nickname"};
ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
.withSelection(selectArgs1, selectArgs2)
.withValue(ContactsContract.CommonDataKinds.Nickname.NAME, nickname)
.build());
ContentProviderResult [] cpResArr = getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
int j=cpResArr.length;
System.out.println(j);
Toast.makeText(getApplicationContext(), "value is updated", Toast.LENGTH_LONG).show();**
I got it worked, below is the piece of code which worked for me.
ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
.withValue(Data.RAW_CONTACT_ID, ContactId)
.withValue(Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE)
.withValue(Nickname.NAME, "Sister")
.withValue(Nickname.TYPE, Nickname.TYPE_CUSTOM)
.withValue(Nickname.LABEL, "Sister")
.build());
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
We need to obtain builder object and than add it to arraylist before calling applybatch.
Refer the following link for further info: http://developer.android.com/reference/android/provider/ContactsContract.CommonDataKinds.Nickname.html
Using eclipse's jdt refactoring framework, I am trying to convert two different code bases to the same names. They are almost identical codebases except that names are different.
Function/Field/Class renaming works fine, but when it comes to parameters it yells at me that the workbench is not created yet. However i'm trying to do this in a headless manor.
private void refactor(String task, IJavaElement element, String new_name) throws CoreException
{
RefactoringStatus status = new RefactoringStatus();
RefactoringContribution contrib = RefactoringCore.getRefactoringContribution(task);
RenameJavaElementDescriptor rnDesc = (RenameJavaElementDescriptor)contrib.createDescriptor();
rnDesc.setFlags(JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING);
rnDesc.setProject(element.getJavaProject().getProject().getName());
rnDesc.setUpdateReferences(true);
rnDesc.setJavaElement(element);
rnDesc.setNewName(new_name);
Refactoring ref = rnDesc.createRefactoring(status);
ref.checkInitialConditions(NULL_MON);
ref.checkFinalConditions(NULL_MON);
Change change = ref.createChange(NULL_MON);
change.perform(NULL_MON);
}
This works fine:
for (IMethod method : type.getMethods())
{
refactor(IJavaRefactorings.RENAME_METHOD, method, {new name});
}
This does not:
for (IMethod method : type.getMethods())
{
for (ILocalVariable param : method.getParameters())
{
refactor(IJavaRefactorings.RENAME_LOCAL_VARIABLE, param, {new name});
}
}
And the error, not really helpful as I said I need to do this in a headless manor {so can't make workbench}
java.lang.IllegalStateException: Workbench has not been created yet.
at org.eclipse.ui.PlatformUI.getWorkbench(PlatformUI.java:92)
at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.install(ASTProvider.java:245)
at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.<init>(ASTProvider.java:236)
at org.eclipse.jdt.internal.ui.JavaPlugin.getASTProvider(JavaPlugin.java:710)
at org.eclipse.jdt.ui.SharedASTProvider.getAST(SharedASTProvider.java:128)
at org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser.parseWithASTProvider(RefactoringASTParser.java:119)
at org.eclipse.jdt.internal.corext.refactoring.rename.RenameLocalVariableProcessor.initAST(RenameLocalVariableProcessor.java:231)
at org.eclipse.jdt.internal.corext.refactoring.rename.RenameLocalVariableProcessor.checkInitialConditions(RenameLocalVariableProcessor.java:218)
at org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring.checkInitialConditions(ProcessorBasedRefactoring.java:203)
UPDATE: Made some progress, now I can refactor functions that are not overrides. But any function that overrides another or an interface screws up:
F_ARGUMENTS = JavaRefactoringDescriptor.class.getDeclaredField("fArguments");
F_ARGUMENTS.setAccessible(true);
private void refactor(IMethod method, String[] names) throws CoreException
{
/* My attempt to fix the interface issues, causes duplicate functions instead of renaming the parameters
IMethod parent = null;
if (method.getDeclaringType().isInterface())
{
parent = MethodChecks.overridesAnotherMethod(method, method.getDeclaringType().newSupertypeHierarchy(NULL_MON));
}
else if (MethodChecks.isVirtual(method))
{
ITypeHierarchy hierarchy = method.getDeclaringType().newTypeHierarchy(NULL_MON);
parent = MethodChecks.isDeclaredInInterface(method, hierarchy, NULL_MON);
if (parent == null)
{
parent = MethodChecks.overridesAnotherMethod(method, hierarchy);
}
}
parent = (parent == null ? method : parent);
if (!method.equals(parent))
{
refactor(parent, names);
return;
}*/
String task = IJavaRefactorings.CHANGE_METHOD_SIGNATURE;
RefactoringStatus status = new RefactoringStatus();
ChangeMethodSignatureRefactoringContribution contrib = (ChangeMethodSignatureRefactoringContribution)RefactoringCore.getRefactoringContribution(task);
ChangeMethodSignatureDescriptor desc = (ChangeMethodSignatureDescriptor)contrib.createDescriptor();
desc.setFlags(JavaRefactoringDescriptor.JAR_MIGRATION |
JavaRefactoringDescriptor.JAR_REFACTORING |
RefactoringDescriptor.MULTI_CHANGE |
RefactoringDescriptor.STRUCTURAL_CHANGE);
Map<String, String> args = null;
try
{
args = (Map<String, String>)F_ARGUMENTS.get(desc);
}
catch (Exception e)
{
e.printStackTrace();
}
String project = method.getJavaProject().getProject().getName();
desc.setProject(method.getJavaProject().getProject().getName());
args.put("input", JavaRefactoringDescriptorUtil.elementToHandle(project, method));
args.put("name", method.getElementName());
args.put("deprecate", "false");
args.put("delegate", "true");
boolean changed = false;
int x = 0;
for (ILocalVariable param : method.getParameters())
{
if (!param.getElementName().equals(names[x]))
{
changed = true;
}
String type = "String"; //Doesn't seem to actually matter as long as they are both the same
String info = type + " " + param.getElementName() + " " + x + " " +
type + " " + names[x] + " false";
args.put("parameter" + (x + 1), info);
x++;
}
if (changed)
{
refactor(desc.createRefactoring(status));
}
}
This is what I came up with:
ChangeSignatureProcessor changeSignatureProcessor = new ChangeSignatureProcessor((IMethod) node.resolveBinding().getJavaElement());
ParameterInfo info=new ParameterInfo("FormContext", "formContext", ParameterInfo.INDEX_FOR_ADDED);
info.setDefaultValue("formContext");
changeSignatureProcessor.getParameterInfos().add(0,info);
RefactoringStatus status = new RefactoringStatus();
CheckConditionsContext context= new CheckConditionsContext();
context.add(new ValidateEditChecker(null));
context.add(new ResourceChangeChecker());
changeSignatureProcessor.checkInitialConditions(monitor);
changeSignatureProcessor.checkFinalConditions(monitor,context);
changeSignatureProcessor.createChange(monitor).perform(monitor);