Ребята, вы должны мне помочь, пожалуйста!
Мое приложение генерирует следующую ошибку при использовании repeat, fixed64 или int64.
com.google.protobuf.InvalidProtocolBufferException: While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either that the input has been truncated or that an embedded message misreported its own length.
at com.google.protobuf.InvalidProtocolBufferException.truncatedMessage(InvalidProtocolBufferException.java:86)
at com.google.protobuf.CodedInputStream$ArrayDecoder.pushLimit(CodedInputStream.java:1224)
at com.google.protobuf.CodedInputStream$ArrayDecoder.readMessage(CodedInputStream.java:921)
at com.google.protobuf.AbstractParser.parsePartialFrom(AbstractParser.java:163)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:197)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:209)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:214)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:49)
at ...
** Проект 1 **
Мой файл Protobuf
syntax = "proto3";
option java_package = "br.com.my.project.view";
option java_outer_classname = "CompanyProtos";
message CompanyResponse {
repeated Company companies = 1;
}
message Company {
string name = 1;
fixed32 id = 2;
fixed64 systemId = 3;
string aliasName = 4;
message Address {
fixed32 addressTypeId = 1;
string streetType = 2;
string streetName = 3;
string streetNumber = 4;
string streetComplement = 5;
string neighborhood = 6;
string city = 7;
string state = 8;
string country = 9;
string zipcode = 10;
}
Address address = 5;
message Phone {
string name = 1;
fixed64 number = 2;
}
repeated Phone phones = 6;
}
Spring Config class
@Configuration
public class SpringConfig extends WebMvcConfigurationSupport {
@Bean
public ViewResolver internalResourceViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(protobufJsonFormatHttpMessageConverter());
super.configureMessageConverters(converters);
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/index.jsp");
}
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
public ProtobufJsonFormatHttpMessageConverter protobufJsonFormatHttpMessageConverter() {
return new ProtobufJsonFormatHttpMessageConverter();
}
}
Класс контроллера
@RestController
@RequestMapping("company")
public class CompanyController {
@Autowired
private ICompanyBusinessService companyBusinessService;
@GetMapping(value = {"/name/{name}"},produces = {MediaType.APPLICATION_JSON_UTF8_VALUE,"application/x-protobuf;charset=UTF-8" })
public CompanyProtos.CompanyResponse getProtobufCompany(
@RequestHeader(value = "messageId", required = false) String tid,
@PathVariable(value = "name", required = false) String name) {
List<Company> companies = companyBusinessService.getCompanies(name);
CompanyProtos.CompanyResponse.Builder builder = CompanyProtos.CompanyResponse.newBuilder();
for(Company c : companies) {
CompanyProtos.Company.Builder companyBuilder = CompanyProtos.Company.newBuilder();
companyBuilder.setName(c.getName());
companyBuilder.setId(c.getId());
companyBuilder.setSystemId(c.getSystemId());
companyBuilder.setAliasName(c.getAliasName());
CompanyProtos.Company.Address.Builder addressBuilder = CompanyProtos.Company.Address.newBuilder();
addressBuilder.setAddressTypeId(c.getAddress().getAddressTypeId());
addressBuilder.setStreetType(c.getAddress().getStreetType());
addressBuilder.setStreetName(c.getAddress().getStreetName());
addressBuilder.setStreetNumber(c.getAddress().getStreetNumber());
addressBuilder.setStreetComplement(c.getAddress().getStreetComplement());
addressBuilder.setNeighborhood(c.getAddress().getNeighborhood());
addressBuilder.setCity(c.getAddress().getCity());
addressBuilder.setState(c.getAddress().getState());
addressBuilder.setCountry(c.getAddress().getCountry());
addressBuilder.setZipcode(c.getAddress().getZipcode());
addressBuilder.setMailbox(c.getAddress().getMailbox());
companyBuilder.setAddress(addressBuilder.build());
for(Phone p : c.getPhones()) {
CompanyProtos.Company.Phone.Builder phoneBuilder = CompanyProtos.Company.Phone.newBuilder();
phoneBuilder.setName(p.getName());
phoneBuilder.setNumber(p.getNumber());
companyBuilder.addPhones(phoneBuilder.build());
}
builder.addCompanies(companyBuilder.build());
}
return builder.build();
}
}
** Проект 2 **
Мой еще один проект. получатель.
....
private ResponseEntity<byte[]> performCall(URI uri, HttpHeaders headers, HttpMethod method) throws Exception {
RestTemplate rest = new RestTemplate();
rest.getMessageConverters().add(new ProtobufHttpMessageConverter());
rest.getMessageConverters().add(new StringHttpMessageConverter());
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
rest.getMessageConverters().add(new ByteArrayHttpMessageConverter());
HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<byte[]> response = rest.exchange(uri, method, request, byte[].class);
return response;
}
public byte[] perform() throws Exception {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://localhost:8080/company/name/MyCompany")
HttpHeaders headers = new HttpHeaders();
headers.set("Accept","application/x-protobuf;charset=UTF-8");
ResponseEntity<byte[]> response = this.performCall(uri, headers, HttpMethod.GET);
return response.getBody();
}
private convertProtobufToObject(){
try {
byte[] result = perform();
CompanyProtos.CompanyResponse companies = CompanyProtos.CompanyResponse.parseFrom(result);
System.out.println();
} catch (Exception e) {
e.printStrackTrace();
}
}
....
Я использую Spring 5.1.4, protobuf-java 3.6.1, protobuf-java-util 3.6.1, protobuf-java-format 1.4, Tomcat 9 и spring-boot-зависимости 2.1.2.RELEASE и .proto файл одинаков для двух проектов.
Когда я использую parseFrom в проекте 1, он работает, но когда я использую в проекте 2, не работает!
** ОБНОВЛЕНИЕ **
Ну, после нескольких тестов я нашел ответ. Проблема была в кодировке Windows (CP1252). Мне нужно было добавить эту конфигурацию при запуске tomcat9:
-Dfile.encoding = CP1252
это работает, но не работает с UTF-8
Вы можете мне помочь?
Спасибо