При синхронизации двух Jira возникают проблемы с кодировкой

При синхронизации двух джир: в одной проект ведется, в другой регулярно обновляется его “зеркало” ломается кодировка для полей title и description.

Что интересно, при запуске из Eclipse все ok, при попытке запустить из командной строки, чтобы потом использовать в CI - проблема.

Запуск из командной строки:
mvn exec:java -Dexec.mainClass="sync" -Dfile.encoding=UTF-8

В pom.xml прописано
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>

Подскажите, плиз, как исправить

Проблема понятна, расскажите еще с помощью чего вы делаете синхронизацию и покажите код синхронизации.

проект запускает TeamCity, вот код синхронизации

import net.rcarz.jiraclient.BasicCredentials;
import net.rcarz.jiraclient.Field;
import net.rcarz.jiraclient.Issue;
import net.rcarz.jiraclient.JiraClient;
import net.rcarz.jiraclient.JiraException;
import net.sf.json.JSONObject;


public class sync {

	
	static String sourceLogin = "xxx";
	static String sourcePassword = "xxx";
	static String sourceUrl = "https://xxx/issues/";
	
	static String targetLogin = "xxx";
	static String targetPassword = "xxx";
	static String targetUrl = "http://xxx/";
	
	static String query = "project = xxx AND issuetype in (Defect, Enhancement)";
	
	final JSONObject obj = new JSONObject();
	
	public static void main(String[] args) throws JiraException {
	
		System.out.println("Connect target jira, URL: " + targetUrl);
		BasicCredentials credsTarget = new BasicCredentials(targetLogin, targetPassword);
		JiraClient jiraTarget = new JiraClient(targetUrl, credsTarget);
        
        
		System.out.println("Connect source jira, URL: " + sourceUrl);
		BasicCredentials credsSource = new BasicCredentials(sourceLogin, sourcePassword);
        JiraClient jiraSource = new JiraClient(sourceUrl, credsSource);
        
        System.out.println("Get issues from source, query: " + query);
        Issue.SearchResult sourceResult = jiraSource.searchIssues(query);
        System.out.println("Total issues found: " + sourceResult.total);
       
        String srcId = "";
        String sourceType = "";
        String sourceStatus = "";
        String sourceDescription = "";
        String sourceSteps = "";
        String sourceExpected = "";
        String sourceActual = "";
        String sourcePriority = "";
        
        String trgId = "";
        String targetType = "";
        String targetPriority = "";
        
        for (Issue sourceIssue : sourceResult.issues) {
        	
        	srcId=sourceIssue.getKey();
        	System.out.println("Start processing issue: " + sourceUrl + sourceIssue.getKey());
        
        
        	System.out.println(" - Check if issue is presented in target jira.");
            Issue.SearchResult targetResult = jiraTarget.searchIssues("project = MRR AND Original = \"" + sourceUrl + "browse/" + srcId + "\"");
            if (targetResult.total==1) {
            	Issue targetIssue = targetResult.issues.get(0);
            	trgId = targetIssue.getKey();;
            	System.out.println(" - It is, ID: " + trgId);
            	System.out.println(" - Check if fields udate s necesary.");
                
                //get source type
                final JSONObject srcType = (JSONObject) sourceIssue.getField(Field.ISSUE_TYPE);
                if (srcType.getString("name").equals("Enhancement")) {
                	sourceType = "Improvement";
                } else if (srcType.getString("name").equals("Defect")) {
                	sourceType = "Bug";
                } else {
               	 System.out.println(" - [ERROR] UNEXPECTED TYPE: " + srcType.getString("name"));
                }
                //get target type
                final JSONObject trgType = (JSONObject) targetIssue.getField(Field.ISSUE_TYPE);
                targetType=trgType.getString("name");
                //update if necessary
                if (!targetType.equals(sourceType)) {
                	System.out.println(" - Update issue type");          
                	targetIssue.update()
                    .field(Field.ISSUE_TYPE, sourceType).execute();
                	targetIssue.refresh();
                }
                
              	
                //get source status
            	final JSONObject srcStatus = (JSONObject) sourceIssue.getField(Field.STATUS);
            	//get target status
                final JSONObject trgStatus = (JSONObject) targetIssue.getField(Field.STATUS);
                //update if necessary
                if (!trgStatus.getString("name").equals(srcStatus.getString("name"))) {
                	System.out.println(" - Update issue status");
                	targetIssue.transition().execute(srcStatus.getString("name"));
                }
                
                //update summary if necessary
                if (!sourceIssue.getField(Field.SUMMARY).equals(targetIssue.getField(Field.SUMMARY))) {
                	System.out.println(" - Update issue Summary");  
                	targetIssue.update()
                     .field(Field.SUMMARY, sourceIssue.getField(Field.SUMMARY)).execute();
                }
                	
                
                //for bug
                sourcePriority="";
                if (sourceType.equals("Bug")) {
                	//get source priority
                	final JSONObject srcPriority = (JSONObject) sourceIssue.getField("customfield_40784");
	               	 
	               	if (srcPriority.getString("value").equals("0-Blocker"))
	               		sourcePriority = "Blocker";
	               	else if (srcPriority.getString("value").equals("1-Critical"))
	               		sourcePriority = "Critical";
	               	else if (srcPriority.getString("value").equals("2-Major"))
	               		sourcePriority = "Major";
	               	else if (srcPriority.getString("value").equals("3-Average"))
	               		sourcePriority = "Minor";
	               	else if (srcPriority.getString("value").equals("4-Minor"))
	               		sourcePriority = "Trivial";
	               	
	              //get target priority
                	final JSONObject trgPriority = (JSONObject) targetIssue.getField(Field.PRIORITY);
                	targetPriority = trgPriority.getString("name");
	               	 
                	//update if necessary  
                    if (!targetPriority.equals(sourcePriority)) {
                    	System.out.println(" - Update issue Priority");
                    	targetIssue.update()
                         .field(Field.PRIORITY, sourcePriority).execute();;
                    	
                    }
	               	
                }
                
                //get source description
                sourceDescription="";
                sourceSteps="";
                sourceExpected="";
                sourceActual="";                
                if (sourceType.equals("Bug")) {
                	try {sourceDescription = (String) sourceIssue.getField(Field.DESCRIPTION);} catch  (Exception e) { }
                	try {sourceSteps = "*Шаги:* \n\n" + (String) sourceIssue.getField("customfield_40788");} catch  (Exception e) { }
               	 	try {sourceExpected = "\n\n *Ожидалось:* \n\n" + (String) sourceIssue.getField("customfield_40112");} catch  (Exception e) { }
               	 	try {sourceActual= "\n\n *Результат:* \n\n" + (String) sourceIssue.getField("customfield_40113") ;} catch  (Exception e) { }
               	 
               	 sourceDescription = sourceDescription + sourceSteps +
               			 sourceExpected  +
               			 sourceActual;               	
               	 
                } else {
               	 try {sourceDescription = (String) sourceIssue.getField(Field.DESCRIPTION);} catch  (Exception e) { }
                }
                
                String targetDescription = "";

                //get target description
                try {targetDescription=(String) targetIssue.getField(Field.DESCRIPTION);} catch  (Exception e) { }
               	//update if necessary  
                if (!targetDescription.equals(sourceDescription)) {
                	System.out.println(" - Update issue Description");
                	targetIssue.update()
                     .field(Field.DESCRIPTION, sourceDescription).execute();;
                	
                }

            } else if (targetResult.total==0) {
            	System.out.println(" - It is not.");
            	System.out.println(" - Add issue to target jira.");
            	System.out.println(" - Summary: " + sourceIssue.getField(Field.SUMMARY));   
            	System.out.println(" - Description: " + sourceIssue.getField(Field.DESCRIPTION));
            	
            	 final JSONObject srcStatus = (JSONObject) sourceIssue.getField(Field.STATUS);
                 
                 final JSONObject srcType = (JSONObject) sourceIssue.getField(Field.ISSUE_TYPE);
                 
                 if (srcType.getString("name").equals("Enhancement")) {
                	 sourceType = "Improvement";
                 } else if (srcType.getString("name").equals("Defect")) {
                	 sourceType = "Bug";
                 } else {
                	 System.out.println(" - [ERROR] UNEXPECTED TYPE: " + srcType.getString("name"));
                 } 
 
                 sourceDescription="";
                 sourceSteps="";
                 sourceExpected="";
                 sourceActual="";
                 if (sourceType.equals("Bug")) {
                	 try {sourceDescription = (String) sourceIssue.getField(Field.DESCRIPTION);} catch  (Exception e) { }
                	 try {sourceSteps = "*Шаги:* \n\n" + (String) sourceIssue.getField("customfield_40788");} catch  (Exception e) { }
                	 try {sourceExpected = "\n\n *Ожидалось:* \n\n" + (String) sourceIssue.getField("customfield_40112");} catch  (Exception e) { }
                	 try {sourceActual= "\n\n *Результат:* \n\n" + (String) sourceIssue.getField("customfield_40113") ;} catch  (Exception e) { }
                	 
                	 sourceDescription = sourceDescription + sourceSteps +
                			 sourceExpected  +
                			 sourceActual;
                	 
                	 final JSONObject srcPriority = (JSONObject) sourceIssue.getField("customfield_40784");
                	 sourcePriority = srcPriority.getString("value");
                	 System.out.println(sourcePriority);   
                	 
                	 if (sourcePriority.equals("0-Blocker"))
                		 targetPriority = "Blocker";
                	 else if (sourcePriority.equals("1-Critical"))
                		 targetPriority = "Critical";
                	 else if (sourcePriority.equals("2-Major"))
                		 targetPriority = "Major";
                	 else if (sourcePriority.equals("3-Average"))
                		 targetPriority = "Minor";
                	 else if (sourcePriority.equals("4-Minor"))
                		 targetPriority = "Trivial";
                 } else {
                	 try {sourceDescription = (String) sourceIssue.getField(Field.DESCRIPTION);} catch  (Exception e) { }
                	 targetPriority = "Major";
                 }
                 
                 
                Issue newIssue = jiraTarget.createIssue("MRR", sourceType)
                    .field(Field.SUMMARY, sourceIssue.getField(Field.SUMMARY))
                    .field(Field.DESCRIPTION, sourceDescription)
                    .field(Field.PRIORITY, targetPriority)
                    .field("customfield_10011", sourceUrl + "browse/" + srcId)
                    .execute();
                System.out.println(" - Issue was created.");            	   
                System.out.println(" - Transition to status: " + srcStatus.getString("name"));
                
                sourceStatus = srcStatus.getString("name");
                if (!sourceStatus.equals("Submitted"))
                	newIssue.transition().execute(srcStatus.getString("name"));
                
            } else {
            	System.out.println(" - [ERROR] DUPLICATE ISSUES");
            }            	
            
        	System.out.println("Finish processing issue.");

	    }	
	
	}
}


  1. В каком именно участке кода страдает кодировка?
  2. Какую версию Jira / JIRA API используете? Ведь для разных версий Jira свои API.
  3. Что за магические явные преобразования типов к JSONObject и String? У Issue есть все необходимые геттеры - для вашего случая getDescription() и getSummary().
  1. Похоже, на этапе извлечения данных (теперь уже с помощью методов getSummary() и getDescription()). Если захардкодить русский текст, его кодировка не портится.

При выполнении через IDE все получаемые значения - в UTF8 (эта кодировка настроена в IDE для проекта), а при запуски из консоли - в системной колировке Windows-1251.

  1. Jira v6.3.1

  2. Спасибо, исправила.

Пока сделали такой воркэраунд:

  • кодировку IDE сменили на системную (windows-1251), чтобы работало одинаково там и там
  • после получения строк (будут в windows-1251) делаем преобразование кодировки, чтобы результат выглядел удобоваримо после записи в джиру:
    sourceDescription = new String(sourceDescription.getBytes(“windows-1251”),“utf8”);

Если посоветуете другое решение, будем признательны, т.к. привязываться к системной кодировке не хочется."

Мораль: я починила, но хаком, а хочется узнать как надо было делать по-нормальному.