Foundation utilities for the Solenopsis Salesforce SOAP framework.
This library provides low-level utilities used by the Solenopsis framework for Salesforce SOAP operations:
- solenopsis/soap - Salesforce SOAP client generation (Apex, Metadata, Enterprise, Partner, Tooling APIs)
- solenopsis/session - Salesforce session management and authentication
Core utilities for Apache CXF SOAP clients:
- Configure SOAP service headers and endpoints
- Compute QNames from
@WebServiceClientannotations - Set custom headers for Salesforce API calls
- Manage SOAP factory instances
- String concatenation with separators
- URL encoding
- Unique ID generation with UUID
- Validation (
requireNonBlank) - Serialization/deserialization (internal use only)
- Safe file I/O with validation
- File existence checking
- FileInputStream creation with proper error handling
- ArrayUtil - Array validation and null-checking
- ClassUtil - Reflection and package utilities
- LoggerUtil - Enhanced logging with varargs support
- ObjectUtil - Object validation helpers
- UrlUtil - URL parsing and manipulation
This library is currently published via packagecloud.io. Maven Central publishing is planned (see #177).
<dependency>
<groupId>org.flossware</groupId>
<artifactId>commons-java</artifactId>
<version>LATEST</version> <!-- Check releases: https://github.com/FlossWare/commons-java/releases -->
</dependency>
<repositories>
<repository>
<id>flossware-packagecloud</id>
<url>https://packagecloud.io/flossware/java/maven2</url>
</repository>
</repositories>import org.flossware.commons.util.SoapUtil;
// Create a port and set Salesforce endpoint
MetadataPortType port = portFactory.createPort();
SoapUtil.setUrl(port, "https://na1.salesforce.com/services/Soap/m/58.0");import org.flossware.commons.util.SoapUtil;
import javax.xml.namespace.QName;
Service service = new MetadataService();
QName sessionHeaderQName = new QName("http://soap.sforce.com/2006/04/metadata", "SessionHeader");
SoapUtil.setHeader(service, sessionHeaderQName, sessionHeaderValue);import org.flossware.commons.util.SoapUtil;
QName qname = SoapUtil.computeQName(MetadataService.class);
// Returns QName based on @WebServiceClient annotationimport org.flossware.commons.util.StringUtil;
// Validate non-blank strings
String apiUrl = StringUtil.requireNonBlank(url, "Salesforce URL cannot be blank");
// Generate unique IDs
String requestId = StringUtil.generateUniqueString("sfdc-request-");import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.InputStream;
// Modern approach using java.nio.file.Files
Path wsdlPath = Paths.get("src/main/resources/wsdl/metadata.wsdl");
if (!Files.exists(wsdlPath)) {
throw new IllegalArgumentException("WSDL file not found: " + wsdlPath);
}
// Create input stream
InputStream inputStream = Files.newInputStream(wsdlPath);- Java 17+
- Apache CXF 4.0+ - For SOAP client support
- Apache Commons Lang3 3.17+ - Baseline utilities
# Build and run tests
mvn clean install
# Run tests only
mvn test
# Skip tests
mvn clean install -DskipTestsThe library maintains excellent test coverage with 321 tests:
Coverage Metrics:
- 🎯 96% instruction coverage (2,034/2,110 instructions)
- ✅ 84% branch coverage (132/158 branches)
- 🎯 100% method coverage (135/135 methods)
- 🎯 96% line coverage (437/453 lines)
- 🎯 100% class coverage
Test Suite Includes:
- Input validation edge cases (null, empty, whitespace)
- Exception handling verification (including defensive paths)
- SOAP utilities with Mockito-based integration tests
- String operations, encoding, and serialization
- File operations with temporary files
- Reflection-based tests for private constructors and utility class enforcement
- Mock-based tests for unreachable exception paths
- Defensive code validation via reflection
- ObjectInputFilter comprehensive security testing:
- ALLOWED path: trusted packages (org.flossware., java.lang., java.util.*, arrays)
- REJECTED path: untrusted packages with warning logging
- UNDECIDED path: null serialClass during metadata processing
- Complex object graph deserialization (ArrayList, nested structures)
All 321 tests pass with 0 failures. JaCoCo coverage reports are generated with each build.
Remaining Branch Coverage (26 of 158 branches, 84%):
- Minor edge cases in conditional logic
This library sits at the foundation of the Solenopsis stack:
┌─────────────────────────┐
│ Solenopsis Session │ ← Authentication & session mgmt
└───────────┬─────────────┘
│ depends on
┌───────────▼─────────────┐
│ Solenopsis SOAP │ ← Salesforce API clients
└───────────┬─────────────┘
│ depends on
┌───────────▼─────────────┐
│ commons-java │ ← Foundation utilities (this)
└─────────────────────────┘
For security vulnerability reporting, please use GitHub Issues.
The serialization methods in StringUtil are for internal use only:
- WARNING: Java deserialization of untrusted data is a security risk
- Only deserialize data from trusted sources
- Consider using JSON or XML for external data
- These methods are used internally for session caching
- ObjectInputFilter protection added in v1.30 to restrict deserialization to trusted packages
Several methods are deprecated and scheduled for removal in version 2.0:
toString(Serializable)- Use JSON libraries (Jackson, Gson) insteadfromString(String)- Use JSON libraries (Jackson, Gson) insteadtoCompressedString(Serializable)- Use JSON with compression insteadfromCompressedString(String)- Use JSON with decompression instead
Migration Example:
// Old (deprecated)
String serialized = StringUtil.toString(myObject);
MyClass obj = StringUtil.fromString(serialized);
// New (recommended)
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(myObject);
MyClass obj = mapper.readValue(json, MyClass.class);getFileInputStream(File)- UseFiles.newInputStream(Path)insteadgetFileInputStream(String)- UseFiles.newInputStream(Path)insteadensureFileExists(File)- UseFiles.exists(Path)with proper exception handlingensureFileExists(String)- UseFiles.exists(Path)with proper exception handling
Migration Example:
// Old (deprecated)
File file = FileUtil.ensureFileExists("data.txt");
FileInputStream fis = FileUtil.getFileInputStream(file);
// New (recommended)
Path path = Paths.get("data.txt");
if (!Files.exists(path)) {
throw new IllegalArgumentException("File not found: " + path);
}
InputStream is = Files.newInputStream(path);ensureString(String)- UserequireNonBlank(String)insteadensureString(String, String)- UserequireNonBlank(String, String)instead
Timeline:
- v1.x: Current stable branch (security fixes and critical bugs only)
- v2.0: Planned removal of all deprecated methods
See release notes in GitHub Releases for version history.
See CONTRIBUTING.md for detailed guidelines including:
- Code style and standards (Google Java Style Guide)
- Testing requirements (93% coverage minimum)
- Pull request process
- Commit message format
Quick start:
- Fork and clone the repository
- Run
mvn verifyto ensure all tests pass - Make changes following our coding standards
- Submit PR with tests and documentation
- Maintain 96% coverage minimum
GNU General Public License, Version 3 - See LICENSE file
- Source: https://github.com/FlossWare/commons-java
- Issues: https://github.com/FlossWare/commons-java/issues
- Solenopsis SOAP: https://github.com/solenopsis/soap
- Solenopsis Session: https://github.com/solenopsis/session
- Package Repository: https://packagecloud.io/flossware/java
See GitHub Releases for detailed version history.